How use sqlite + fdbm library with threading on the iPhone

我怕爱的太早我们不能终老 提交于 2019-12-04 11:50:18

The singleton method is a fine idea, although it doesn't look like you're actually initializing currentDbSingleton anywhere... Assuming you fix that and you return a valid DB connection, I don't think that's you're problem.

The 'library routine called out of sequence' errors you mention tip me off that the library you're using (SQLite or FMDB) expects method/function calls to be made in a particular sequence. What you likely have is a concurrency problem where two or more threads are making calls to the same library, and while each may use the correct order, if they're "talking at the same time", so to speak, the library may receive calls out of the expected sequence. What you want is for a set of calls to be treated as an atomic unit, such that they cannot overlap or intermingle.

This is where NSOperation comes in. Subclassing it allows you treat a bunch of code as a "single encapsulated task" — you'll probably want to design for non-concurrent operation. The class documentation has details that explain how to implement your logic within an NSOperation.


Edit: (After asker clarified the question with addition context)

Since the problem is occurring in checkError, and that method is called from multiple places in your linked .m file, there's a good chance that you're calling hadError at an incorrect time. (Is it called after a transaction is closed? What if it is called after the next transaction has begun?)

For example, what would happen if fillCache is called while the previous call is still accessing the database? Your transaction management methods look extremely suspect in this regard. For example, if someone calls beginTransaction and inTransaction is YES, the method returns without doing anything (that is, it doesn't call to the FMDatabase ivar at all). What you probably want is for the second caller to wait until the first caller finishes its transaction. (Unless FMDatabase supports concurrent transactions, in which case you'd want to call beginTransaction on it regardless.)

If you haven't already, read this Apple article on Objective-C thread synchronization. Next, consult the documentation for NSLock (particularly lockBeforeDate:) and associated sample code. Inside your -[Db beginTransaction] method, you'll probably want to block on obtaining a lock.

You also have several peculiar class methods, such as +allocWithZone: — opt to use +inizialize (which is called automatically by the runtime when the class is first referenced) if you can, so the class can take care of initializing itself without the need for a manual call. (I'm guessing you call +alloc, then -initWithName:, then feed it back to +setCurrentDb. A convenience method such as +initializeWithPath: that handles all that would be much cleaner.)

There are numerous other gotchas, such as the fact that +setCurrentDb: could swap out the singleton object regardless of whether a transaction is in process (and the old singleton is not released), +currentDb raises an exception where it should probably just create the singleton instance, etc. However, the biggest problems you're facing are getting concurrency right. I think that implementing locks to protect the FMDatabase reference is a step in the right direction, but just wrapping method X in an NSOperation isn't going to do it for you. Every point in your code that references theDb without the guarantee that nobody else is doing so risks a crash. Don't feel bad if this seems hard, because it is.

Last random suggestion: change your methods TypeForField:Type: and ValueForField:Name:Type: to typeForFieldName:typeName: and valueForResultSet:fieldName:typeName: respectively. Strive for accuracy, readability, and matching convention.

I finally found a working solution.

The idea is build a database pool of connection and open twice the db. Use one connection for the main thread and the another for the background.

Everything is now in http://code.google.com/p/chibiorm/

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!