Răsfoiți Sursa

Async transactions

August Mueller 9 ani în urmă
părinte
comite
c1c39c0609
4 a modificat fișierele cu 75 adăugiri și 8 ștergeri
  1. 1 0
      src/fmdb/FMDatabaseAdditions.m
  2. 2 0
      src/fmdb/FMDatabaseQueue.h
  3. 11 4
      src/fmdb/FMDatabaseQueue.m
  4. 61 4
      src/sample/main.m

+ 1 - 0
src/fmdb/FMDatabaseAdditions.m

@@ -38,6 +38,7 @@ - (NSString*)stringForQuery:(NSString*)query, ... {
     RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSString *, stringForColumnIndex);
     RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSString *, stringForColumnIndex);
 }
 }
 
 
+#pragma message "FIXME: rename this integer? Or maybe give a size like uint32 or something along those lines?"
 - (int)intForQuery:(NSString*)query, ... {
 - (int)intForQuery:(NSString*)query, ... {
     RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(int, intForColumnIndex);
     RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(int, intForColumnIndex);
 }
 }

+ 2 - 0
src/fmdb/FMDatabaseQueue.h

@@ -165,6 +165,8 @@
 
 
 - (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block;
 - (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block;
 
 
+- (void)inBackgroundTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block;
+
 /** Synchronously perform database operations on queue, using deferred transactions.
 /** Synchronously perform database operations on queue, using deferred transactions.
 
 
  @param block The code to be run on the queue of `FMDatabaseQueue`
  @param block The code to be run on the queue of `FMDatabaseQueue`

+ 11 - 4
src/fmdb/FMDatabaseQueue.m

@@ -189,9 +189,12 @@ - (void)inDatabase:(void (^)(FMDatabase *db))block isAsync:(BOOL)isAsync {
 }
 }
 
 
 
 
-- (void)beginTransaction:(BOOL)useDeferred withBlock:(void (^)(FMDatabase *db, BOOL *rollback))block {
+- (void)beginTransaction:(BOOL)useDeferred isAsync:(BOOL)isAsync withBlock:(void (^)(FMDatabase *db, BOOL *rollback))block {
     FMDBRetain(self);
     FMDBRetain(self);
-    dispatch_sync(_queue, ^() { 
+    
+    void (*dispatch_function)(dispatch_queue_t queue, dispatch_block_t block) = isAsync ? dispatch_async : dispatch_sync;
+    
+    dispatch_function(_queue, ^() {
         
         
         BOOL shouldRollback = NO;
         BOOL shouldRollback = NO;
         
         
@@ -216,11 +219,15 @@ - (void)beginTransaction:(BOOL)useDeferred withBlock:(void (^)(FMDatabase *db, B
 }
 }
 
 
 - (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block {
 - (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block {
-    [self beginTransaction:YES withBlock:block];
+    [self beginTransaction:YES isAsync:NO withBlock:block];
 }
 }
 
 
 - (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block {
 - (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block {
-    [self beginTransaction:NO withBlock:block];
+    [self beginTransaction:NO isAsync:NO withBlock:block];
+}
+
+- (void)inBackgroundTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block {
+    [self beginTransaction:NO isAsync:YES withBlock:block];
 }
 }
 
 
 - (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block {
 - (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block {

+ 61 - 4
src/sample/main.m

@@ -55,8 +55,6 @@ int main (int argc, const char * argv[]) {
         
         
         // 3.0, async stuff.
         // 3.0, async stuff.
         
         
-        
-        
         [queue inDatabase:^(FMDatabase *adb) {
         [queue inDatabase:^(FMDatabase *adb) {
             [adb setShouldCacheStatements:YES];
             [adb setShouldCacheStatements:YES];
             [adb setCrashOnErrors:YES];
             [adb setCrashOnErrors:YES];
@@ -86,7 +84,6 @@ int main (int argc, const char * argv[]) {
                 
                 
             }];
             }];
             
             
-            
             OSAtomicIncrement32(&submitCount);
             OSAtomicIncrement32(&submitCount);
         });
         });
         
         
@@ -94,13 +91,73 @@ int main (int argc, const char * argv[]) {
         
         
         FMDBQuickCheck(submitCount == 40);
         FMDBQuickCheck(submitCount == 40);
         
         
-        
         // This will block till all the above async stuff is done.
         // This will block till all the above async stuff is done.
         [queue inDatabase:^(FMDatabase *adb) {
         [queue inDatabase:^(FMDatabase *adb) {
             NSLog(@"done?");
             NSLog(@"done?");
             FMDBQuickCheck(updateCount == 40);
             FMDBQuickCheck(updateCount == 40);
         }];
         }];
         
         
+        
+        
+        
+        {
+            // Let's do async transactions now.
+            
+            updateCount = 0;
+            submitCount = 0;
+            
+            [queue inBackgroundTransaction:^(FMDatabase *adb, BOOL *rollback) {
+                 [adb executeUpdate:@"delete from threeasync"];
+            }];
+            
+            
+            [queue inDatabase:^(FMDatabase *adb) {
+                int count = [adb intForQuery:@"select count(*) from threeasync"];
+                FMDBQuickCheck(count == 0);
+            }];
+            
+            
+            dispatch_apply(20, dispatch_get_global_queue(0, DISPATCH_QUEUE_PRIORITY_DEFAULT), ^(size_t idx) {
+                
+                [queue inBackgroundTransaction:^(FMDatabase *adb, BOOL *rollback) {
+                    
+                    if (idx % 2 == 0) {
+                        usleep(50); // artificial delay.
+                    }
+                    
+                    if (idx % 3 == 0) {
+                        usleep(100); // another artificial delay.
+                    }
+                    
+                    [adb executeUpdate:@"insert into threeasync (foo) values (?)", @(idx)];
+                    [adb executeUpdate:@"insert into threeasync (foo) values (?)", @(idx * 2)];
+                    [adb executeUpdate:@"insert into threeasync (foo) values (?)", @(idx * 4)];
+                    [adb executeUpdate:@"insert into threeasync (foo) values (?)", @(idx * 8)];
+                    
+                    FMDBQuickCheck(![adb hadError]);
+                    
+                    OSAtomicIncrement32(&updateCount);
+                    
+                }];
+                
+                
+                OSAtomicIncrement32(&submitCount);
+            });
+            
+            NSLog(@"submitCount: %d", submitCount);
+            
+            FMDBQuickCheck(submitCount == 20);
+            
+            // This will block till all the above async stuff is done.
+            [queue inDatabase:^(FMDatabase *adb) {
+                NSLog(@"done?");
+                FMDBQuickCheck(updateCount == 20);
+                
+                int count = [adb intForQuery:@"select count(*) from threeasync"];
+                
+                FMDBQuickCheck(count == 80);
+            }];
+        }
     }
     }