BNZTransaction
Abstract: a transaction collects a set of BNZAtomicChange objects that can be applied in an ACID way
A BNZTransaction collects a set of atomic changes that later are applied in an "all of them or
none of them" fashion. A transaction implements a state machine (see the BNZTransactionStatus enum
documentation for details); it always starts ACTIVE. During this phase, atomic changes are collected. When
a transaction is committed (by calling commit), the changes are applied one after another. If one goes
wrong, the whole transaction is rolled back, which means, the changes are undone.
Every transaction is initially associated with a NSThread and it can only be committed or rolled back within
the context of this thread.
Usually, objects that participate in the BNZTransactionalNotificationCenter framework will use the current
transaction to create changes and to find changes that have been done within their own thread to
decide which values to return in getters. this way, a change in a thread is visible even before the transaction
is committed but they are hidden outside the thread until committed.
Example:
//getter of a transactional object
- (NSString*)firstName {
//retrieve transaction of current thread
BNZTransaction transaction = [[BNZTransactionalNotificationCenter defaultCenter] currentTransaction];
//retrieve the last change of the same type that has already been done
id change = [transaction lastChangeOfType:"PersonFirstNameChange" onTarget:self]; //the object that is returned here depends on the setFirstName implementation!
//if there was such a change, pretend to have the new value
if (change != nil) {
return [change newFirstName];
}
//no such change in current thread, return field value
return myFirstName;
}
Note: there are static helper methods in BNZTransactionalNotificationCenter as well as in
BNZAtomicPropertyChange that allow the implementation of the setters and getters in a
transactional object to be much easier, maybe even only one line
This will result in a behavior like this:
- (void)sameThread {
Person p = [[Person alloc] initWithfirstName:"Alice"]; //p is named Alice now
//do not immediately commit each change
[[[BNZTransactionalNotificationCenter defaultCenter] currentTransaction] turnOffAutoCommit];
//change the name to something new
[p setName:"Bob"];
//change is visible, as expected
NSLog("Person is called %(a) in same thread", [person firstName]); //fn will be "Bob" even without commit
//change is not visible in another thread
[NSThread detachNewthreadSelector:(a)selector(otherThread:) toTarget:self withObject:p]; //will still yield "Alice"
//commit changes
[transaction commit];
//change is now also visible in another thread
[NSThread detachNewthreadSelector:(a)selector(otherThread:) toTarget:self withObject:p]; //will yield "Bob"
}
- (void)otherThread:(Person*)person {
//should create autoreleasepool:)
NSLog((a)"Person is called %(a) in other thread", [person firstName]);
}
(Last Updated 8/31/2006)
HTML documentation generated by HeaderDoc