mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-02-05 20:45:49 +01:00
move GameLock class from DBUtils to GameUtils
This commit is contained in:
parent
ce6eca3fe5
commit
c144503630
8 changed files with 120 additions and 120 deletions
|
@ -68,7 +68,7 @@ public class BoardActivity extends XWActivity
|
|||
|
||||
private BoardView m_view;
|
||||
private int m_jniGamePtr;
|
||||
private DBUtils.GameLock m_gameLock;
|
||||
private GameUtils.GameLock m_gameLock;
|
||||
private CurGameInfo m_gi;
|
||||
CommsTransport m_xport;
|
||||
private Handler m_handler;
|
||||
|
@ -1053,7 +1053,7 @@ public class BoardActivity extends XWActivity
|
|||
{
|
||||
if ( 0 == m_jniGamePtr ) {
|
||||
Assert.assertNull( m_gameLock );
|
||||
m_gameLock = new DBUtils.GameLock( m_path, true ).lock();
|
||||
m_gameLock = new GameUtils.GameLock( m_path, true ).lock();
|
||||
|
||||
byte[] stream = GameUtils.savedGame( this, m_gameLock );
|
||||
XwJNI.gi_from_stream( m_gi, stream );
|
||||
|
|
|
@ -28,11 +28,8 @@ import java.util.StringTokenizer;
|
|||
import android.content.ContentValues;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
|
@ -67,88 +64,15 @@ public class DBUtils {
|
|||
boolean sourceLocal;
|
||||
}
|
||||
|
||||
|
||||
// Implements read-locks and write-locks per game. A read lock is
|
||||
// obtainable when other read locks are granted but not when a
|
||||
// write lock is. Write-locks are exclusive.
|
||||
public static class GameLock {
|
||||
private String m_path;
|
||||
private boolean m_isForWrite;
|
||||
private ReentrantReadWriteLock m_rwlock;
|
||||
|
||||
// This will leak empty ReentrantReadWriteLock instances for
|
||||
// now.
|
||||
private static HashMap<String, ReentrantReadWriteLock>
|
||||
s_locks = new HashMap<String,ReentrantReadWriteLock>();
|
||||
|
||||
public GameLock( String path, boolean isForWrite )
|
||||
{
|
||||
m_path = path;
|
||||
m_isForWrite = isForWrite;
|
||||
synchronized( s_locks ) {
|
||||
if ( s_locks.containsKey( m_path ) ) {
|
||||
m_rwlock = s_locks.get( m_path );
|
||||
} else {
|
||||
m_rwlock = new ReentrantReadWriteLock();
|
||||
s_locks.put( path, m_rwlock );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public GameLock lock()
|
||||
{
|
||||
getLock().lock();
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean tryLock()
|
||||
{
|
||||
boolean gotIt = false;
|
||||
synchronized( s_locks ) {
|
||||
boolean hasWaiters = m_isForWrite && m_rwlock.isWriteLocked();
|
||||
if ( !hasWaiters ) {
|
||||
getLock().lock();
|
||||
gotIt = true;
|
||||
}
|
||||
}
|
||||
return gotIt;
|
||||
}
|
||||
|
||||
public void unlock()
|
||||
{
|
||||
synchronized( s_locks ) {
|
||||
getLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public String getPath()
|
||||
{
|
||||
return m_path;
|
||||
}
|
||||
|
||||
// used only for asserts
|
||||
public boolean canWrite()
|
||||
{
|
||||
return m_isForWrite && m_rwlock.isWriteLocked();
|
||||
}
|
||||
|
||||
private Lock getLock()
|
||||
{
|
||||
Lock lock = m_isForWrite? m_rwlock.writeLock()
|
||||
: m_rwlock.readLock();
|
||||
return lock;
|
||||
}
|
||||
}
|
||||
|
||||
public static GameSummary getSummary( Context context, String file )
|
||||
{
|
||||
DBUtils.GameLock lock = new DBUtils.GameLock( file, false ).lock();
|
||||
GameUtils.GameLock lock = new GameUtils.GameLock( file, false ).lock();
|
||||
GameSummary result = getSummary( context, lock );
|
||||
lock.unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static GameSummary getSummary( Context context, DBUtils.GameLock lock )
|
||||
public static GameSummary getSummary( Context context, GameUtils.GameLock lock )
|
||||
{
|
||||
initDB( context );
|
||||
GameSummary summary = null;
|
||||
|
@ -259,7 +183,7 @@ public class DBUtils {
|
|||
return summary;
|
||||
} // getSummary
|
||||
|
||||
public static void saveSummary( Context context, DBUtils.GameLock lock,
|
||||
public static void saveSummary( Context context, GameUtils.GameLock lock,
|
||||
GameSummary summary )
|
||||
{
|
||||
Assert.assertTrue( lock.canWrite() );
|
||||
|
@ -503,8 +427,8 @@ public class DBUtils {
|
|||
}
|
||||
}
|
||||
|
||||
public static void saveGame( Context context, GameLock lock, byte[] bytes,
|
||||
boolean setCreate )
|
||||
public static void saveGame( Context context, GameUtils.GameLock lock,
|
||||
byte[] bytes, boolean setCreate )
|
||||
{
|
||||
Assert.assertTrue( lock.canWrite() );
|
||||
String path = lock.getPath();
|
||||
|
@ -534,7 +458,7 @@ public class DBUtils {
|
|||
}
|
||||
}
|
||||
|
||||
public static byte[] loadGame( Context context, GameLock lock )
|
||||
public static byte[] loadGame( Context context, GameUtils.GameLock lock )
|
||||
{
|
||||
String path = lock.getPath();
|
||||
Assert.assertNotNull( path );
|
||||
|
@ -557,7 +481,7 @@ public class DBUtils {
|
|||
return result;
|
||||
}
|
||||
|
||||
public static void deleteGame( Context context, GameLock lock )
|
||||
public static void deleteGame( Context context, GameUtils.GameLock lock )
|
||||
{
|
||||
initDB( context );
|
||||
synchronized( s_dbHelper ) {
|
||||
|
|
|
@ -85,7 +85,7 @@ public class GameConfig extends XWActivity
|
|||
private String m_path;
|
||||
private CurGameInfo m_gi;
|
||||
private CurGameInfo m_giOrig;
|
||||
private DBUtils.GameLock m_gameLock;
|
||||
private GameUtils.GameLock m_gameLock;
|
||||
private int m_whichPlayer;
|
||||
// private Spinner m_roleSpinner;
|
||||
// private Spinner m_connectSpinner;
|
||||
|
@ -395,7 +395,7 @@ public class GameConfig extends XWActivity
|
|||
m_giOrig = new CurGameInfo( this );
|
||||
// Lock in case we're going to config. We *could* re-get the
|
||||
// lock once the user decides to make changes. PENDING.
|
||||
m_gameLock = new DBUtils.GameLock( m_path, true ).lock();
|
||||
m_gameLock = new GameUtils.GameLock( m_path, true ).lock();
|
||||
GameUtils.loadMakeGame( this, gamePtr, m_giOrig, m_gameLock );
|
||||
m_gameStarted = XwJNI.model_getNMoves( gamePtr ) > 0
|
||||
|| XwJNI.comms_isConnected( gamePtr );
|
||||
|
|
|
@ -37,8 +37,8 @@ public class GameConverter {
|
|||
Utils.logf( "GameConverter::convert() converting %s",
|
||||
game );
|
||||
byte[] bytes = savedGame( context, game );
|
||||
DBUtils.GameLock lock =
|
||||
new DBUtils.GameLock( game, true ).lock();
|
||||
GameUtils.GameLock lock =
|
||||
new GameUtils.GameLock( game, true ).lock();
|
||||
DBUtils.saveGame( context, lock, bytes, true );
|
||||
lock.unlock();
|
||||
context.deleteFile( game );
|
||||
|
|
|
@ -30,6 +30,10 @@ import java.io.InputStream;
|
|||
import android.net.Uri;
|
||||
import java.util.ArrayList;
|
||||
import android.content.res.AssetManager;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.HashMap;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.eehouse.android.xw4.jni.*;
|
||||
|
@ -37,17 +41,89 @@ import org.eehouse.android.xw4.jni.CurGameInfo.DeviceRole;
|
|||
|
||||
public class GameUtils {
|
||||
|
||||
// Implements read-locks and write-locks per game. A read lock is
|
||||
// obtainable when other read locks are granted but not when a
|
||||
// write lock is. Write-locks are exclusive.
|
||||
public static class GameLock {
|
||||
private String m_path;
|
||||
private boolean m_isForWrite;
|
||||
private ReentrantReadWriteLock m_rwlock;
|
||||
|
||||
// This will leak empty ReentrantReadWriteLock instances for
|
||||
// now.
|
||||
private static HashMap<String, ReentrantReadWriteLock>
|
||||
s_locks = new HashMap<String,ReentrantReadWriteLock>();
|
||||
|
||||
public GameLock( String path, boolean isForWrite )
|
||||
{
|
||||
m_path = path;
|
||||
m_isForWrite = isForWrite;
|
||||
synchronized( s_locks ) {
|
||||
if ( s_locks.containsKey( m_path ) ) {
|
||||
m_rwlock = s_locks.get( m_path );
|
||||
} else {
|
||||
m_rwlock = new ReentrantReadWriteLock();
|
||||
s_locks.put( path, m_rwlock );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public GameLock lock()
|
||||
{
|
||||
getLock().lock();
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean tryLock()
|
||||
{
|
||||
boolean gotIt = false;
|
||||
synchronized( s_locks ) {
|
||||
boolean hasWaiters = m_isForWrite && m_rwlock.isWriteLocked();
|
||||
if ( !hasWaiters ) {
|
||||
getLock().lock();
|
||||
gotIt = true;
|
||||
}
|
||||
}
|
||||
return gotIt;
|
||||
}
|
||||
|
||||
public void unlock()
|
||||
{
|
||||
synchronized( s_locks ) {
|
||||
getLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public String getPath()
|
||||
{
|
||||
return m_path;
|
||||
}
|
||||
|
||||
// used only for asserts
|
||||
public boolean canWrite()
|
||||
{
|
||||
return m_isForWrite && m_rwlock.isWriteLocked();
|
||||
}
|
||||
|
||||
private Lock getLock()
|
||||
{
|
||||
Lock lock = m_isForWrite? m_rwlock.writeLock()
|
||||
: m_rwlock.readLock();
|
||||
return lock;
|
||||
}
|
||||
}
|
||||
|
||||
private static Object s_syncObj = new Object();
|
||||
|
||||
public static byte[] savedGame( Context context, String path )
|
||||
{
|
||||
DBUtils.GameLock lock = new DBUtils.GameLock( path, false ).lock();
|
||||
GameLock lock = new GameLock( path, false ).lock();
|
||||
byte[] result = savedGame( context, lock );
|
||||
lock.unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static byte[] savedGame( Context context, DBUtils.GameLock lock )
|
||||
public static byte[] savedGame( Context context, GameLock lock )
|
||||
{
|
||||
return DBUtils.loadGame( context, lock );
|
||||
} // savedGame
|
||||
|
@ -56,8 +132,8 @@ public class GameUtils {
|
|||
* Open an existing game, and use its gi and comms addr as the
|
||||
* basis for a new one.
|
||||
*/
|
||||
public static void resetGame( Context context, DBUtils.GameLock lockSrc,
|
||||
DBUtils.GameLock lockDest )
|
||||
public static void resetGame( Context context, GameLock lockSrc,
|
||||
GameLock lockDest )
|
||||
{
|
||||
int gamePtr = XwJNI.initJNI();
|
||||
CurGameInfo gi = new CurGameInfo( context );
|
||||
|
@ -95,7 +171,7 @@ public class GameUtils {
|
|||
|
||||
public static void resetGame( Context context, String pathIn )
|
||||
{
|
||||
DBUtils.GameLock lock = new DBUtils.GameLock( pathIn, true )
|
||||
GameLock lock = new GameLock( pathIn, true )
|
||||
.lock();
|
||||
tellRelayDied( context, lock, true );
|
||||
resetGame( context, lock, lock );
|
||||
|
@ -103,14 +179,14 @@ public class GameUtils {
|
|||
}
|
||||
|
||||
private static GameSummary summarizeAndClose( Context context,
|
||||
DBUtils.GameLock lock,
|
||||
GameLock lock,
|
||||
int gamePtr, CurGameInfo gi )
|
||||
{
|
||||
return summarizeAndClose( context, lock, gamePtr, gi, null );
|
||||
}
|
||||
|
||||
private static GameSummary summarizeAndClose( Context context,
|
||||
DBUtils.GameLock lock,
|
||||
GameLock lock,
|
||||
int gamePtr, CurGameInfo gi,
|
||||
FeedUtilsImpl feedImpl )
|
||||
{
|
||||
|
@ -135,7 +211,7 @@ public class GameUtils {
|
|||
return summary;
|
||||
}
|
||||
|
||||
public static GameSummary summarize( Context context, DBUtils.GameLock lock )
|
||||
public static GameSummary summarize( Context context, GameLock lock )
|
||||
{
|
||||
int gamePtr = XwJNI.initJNI();
|
||||
CurGameInfo gi = new CurGameInfo( context );
|
||||
|
@ -146,10 +222,10 @@ public class GameUtils {
|
|||
|
||||
public static String dupeGame( Context context, String pathIn )
|
||||
{
|
||||
DBUtils.GameLock lockSrc = new DBUtils.GameLock( pathIn, false ).lock();
|
||||
GameLock lockSrc = new GameLock( pathIn, false ).lock();
|
||||
String newName = newName( context );
|
||||
DBUtils.GameLock lockDest =
|
||||
new DBUtils.GameLock( newName, true ).lock();
|
||||
GameLock lockDest =
|
||||
new GameLock( newName, true ).lock();
|
||||
resetGame( context, lockSrc, lockDest );
|
||||
lockDest.unlock();
|
||||
lockSrc.unlock();
|
||||
|
@ -159,7 +235,7 @@ public class GameUtils {
|
|||
public static void deleteGame( Context context, String path, boolean informNow )
|
||||
{
|
||||
// does this need to be synchronized?
|
||||
DBUtils.GameLock lock = new DBUtils.GameLock( path, true );
|
||||
GameLock lock = new GameLock( path, true );
|
||||
if ( lock.tryLock() ) {
|
||||
tellRelayDied( context, lock, informNow );
|
||||
DBUtils.deleteGame( context, lock );
|
||||
|
@ -168,14 +244,14 @@ public class GameUtils {
|
|||
}
|
||||
|
||||
public static void loadMakeGame( Context context, int gamePtr,
|
||||
CurGameInfo gi, DBUtils.GameLock lock )
|
||||
CurGameInfo gi, GameLock lock )
|
||||
{
|
||||
loadMakeGame( context, gamePtr, gi, null, lock );
|
||||
}
|
||||
|
||||
public static void loadMakeGame( Context context, int gamePtr,
|
||||
CurGameInfo gi, UtilCtxt util,
|
||||
DBUtils.GameLock lock )
|
||||
GameLock lock )
|
||||
{
|
||||
byte[] stream = savedGame( context, lock );
|
||||
XwJNI.gi_from_stream( gi, stream );
|
||||
|
@ -194,7 +270,7 @@ public class GameUtils {
|
|||
}
|
||||
|
||||
public static void saveGame( Context context, int gamePtr,
|
||||
CurGameInfo gi, DBUtils.GameLock lock,
|
||||
CurGameInfo gi, GameLock lock,
|
||||
boolean setCreate )
|
||||
{
|
||||
byte[] stream = XwJNI.game_saveToStream( gamePtr, gi );
|
||||
|
@ -205,23 +281,23 @@ public class GameUtils {
|
|||
CurGameInfo gi )
|
||||
{
|
||||
String path = newName( context );
|
||||
DBUtils.GameLock lock =
|
||||
new DBUtils.GameLock( path, true ).lock();
|
||||
GameLock lock =
|
||||
new GameLock( path, true ).lock();
|
||||
saveGame( context, gamePtr, gi, lock, false );
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
public static void saveGame( Context context, byte[] bytes,
|
||||
DBUtils.GameLock lock, boolean setCreate )
|
||||
GameLock lock, boolean setCreate )
|
||||
{
|
||||
DBUtils.saveGame( context, lock, bytes, setCreate );
|
||||
}
|
||||
|
||||
public static DBUtils.GameLock saveGame( Context context, byte[] bytes )
|
||||
public static GameLock saveGame( Context context, byte[] bytes )
|
||||
{
|
||||
String name = newName( context );
|
||||
DBUtils.GameLock lock =
|
||||
new DBUtils.GameLock( name, true ).lock();
|
||||
GameLock lock =
|
||||
new GameLock( name, true ).lock();
|
||||
saveGame( context, bytes, lock, false );
|
||||
return lock;
|
||||
}
|
||||
|
@ -468,7 +544,7 @@ public class GameUtils {
|
|||
int gamePtr = XwJNI.initJNI();
|
||||
CurGameInfo gi = new CurGameInfo( context );
|
||||
FeedUtilsImpl feedImpl = new FeedUtilsImpl( context, path );
|
||||
DBUtils.GameLock lock = new DBUtils.GameLock( path, true );
|
||||
GameLock lock = new GameLock( path, true );
|
||||
if ( lock.tryLock() ) {
|
||||
loadMakeGame( context, gamePtr, gi, feedImpl, lock );
|
||||
|
||||
|
@ -508,7 +584,7 @@ public class GameUtils {
|
|||
public static void replaceDict( Context context, String path,
|
||||
String dict )
|
||||
{
|
||||
DBUtils.GameLock lock = new DBUtils.GameLock( path, true ).lock();
|
||||
GameLock lock = new GameLock( path, true ).lock();
|
||||
byte[] stream = savedGame( context, lock );
|
||||
CurGameInfo gi = new CurGameInfo( context );
|
||||
byte[] dictBytes = GameUtils.openDict( context, dict );
|
||||
|
@ -528,7 +604,7 @@ public class GameUtils {
|
|||
}
|
||||
|
||||
public static void applyChanges( Context context, CurGameInfo gi,
|
||||
CommsAddrRec car, DBUtils.GameLock lock,
|
||||
CommsAddrRec car, GameLock lock,
|
||||
boolean forceNew )
|
||||
{
|
||||
// This should be a separate function, commitChanges() or
|
||||
|
@ -605,7 +681,7 @@ public class GameUtils {
|
|||
}
|
||||
}
|
||||
|
||||
private static void tellRelayDied( Context context, DBUtils.GameLock lock,
|
||||
private static void tellRelayDied( Context context, GameLock lock,
|
||||
boolean informNow )
|
||||
{
|
||||
GameSummary summary = DBUtils.getSummary( context, lock );
|
||||
|
|
|
@ -431,7 +431,7 @@ public class GamesList extends XWListActivity
|
|||
showOKOnlyDialog( R.string.no_copy_network );
|
||||
} else {
|
||||
byte[] stream = GameUtils.savedGame( this, path );
|
||||
DBUtils.GameLock lock = GameUtils.saveGame( this, stream );
|
||||
GameUtils.GameLock lock = GameUtils.saveGame( this, stream );
|
||||
DBUtils.saveSummary( this, lock, summary );
|
||||
lock.unlock();
|
||||
}
|
||||
|
@ -487,7 +487,7 @@ public class GamesList extends XWListActivity
|
|||
String path = null;
|
||||
byte[] bytes = XwJNI.gi_to_stream( gi );
|
||||
if ( null != bytes ) {
|
||||
DBUtils.GameLock lock = GameUtils.saveGame( this, bytes );
|
||||
GameUtils.GameLock lock = GameUtils.saveGame( this, bytes );
|
||||
path = lock.getPath();
|
||||
lock.unlock();
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ public class RelayGameActivity extends XWActivity
|
|||
|
||||
private String m_path;
|
||||
private CurGameInfo m_gi;
|
||||
private DBUtils.GameLock m_gameLock;
|
||||
private GameUtils.GameLock m_gameLock;
|
||||
private CommsAddrRec m_car;
|
||||
private Button m_playButton;
|
||||
private Button m_configButton;
|
||||
|
@ -74,7 +74,7 @@ public class RelayGameActivity extends XWActivity
|
|||
|
||||
int gamePtr = XwJNI.initJNI();
|
||||
m_gi = new CurGameInfo( this );
|
||||
m_gameLock = new DBUtils.GameLock( m_path, true ).lock();
|
||||
m_gameLock = new GameUtils.GameLock( m_path, true ).lock();
|
||||
GameUtils.loadMakeGame( this, gamePtr, m_gi, m_gameLock );
|
||||
m_car = new CommsAddrRec( this );
|
||||
if ( XwJNI.game_hasComms( gamePtr ) ) {
|
||||
|
|
|
@ -89,7 +89,7 @@ public class JNIThread extends Thread {
|
|||
|
||||
private boolean m_stopped = false;
|
||||
private int m_jniGamePtr;
|
||||
private DBUtils.GameLock m_lock;
|
||||
private GameUtils.GameLock m_lock;
|
||||
private Context m_context;
|
||||
private CurGameInfo m_gi;
|
||||
private Handler m_handler;
|
||||
|
@ -111,7 +111,7 @@ public class JNIThread extends Thread {
|
|||
}
|
||||
|
||||
public JNIThread( int gamePtr, CurGameInfo gi, SyncedDraw drawer,
|
||||
DBUtils.GameLock lock, Context context, Handler handler )
|
||||
GameUtils.GameLock lock, Context context, Handler handler )
|
||||
{
|
||||
m_jniGamePtr = gamePtr;
|
||||
m_gi = gi;
|
||||
|
|
Loading…
Add table
Reference in a new issue