addNoError on the Collection Class

Forums for specific tips, techniques and example code
ConvertFromOldNGs
Posts: 5321
Joined: Wed Aug 05, 2009 5:19 pm

addNoError on the Collection Class

Postby ConvertFromOldNGs » Fri Aug 07, 2009 2:16 pm

by Paul Mathews >> Tue, 13 Jul 1999 8:56:55 GMT

A usefull method on the Collection class,

addNoError(pMemberType : MemberType)updating;

// Date: 14 July 1999
// User: paulm , C&M Systems Group
begin

if not self.includes(pMemberType) then
self.add(pMemberType);
endif;
end;

Paul Mathews
pem@cmsystemsgroup.com.au
Phone: [612] (99717384) Fax[612] (99711679)
(Dee Why,Sydney,Australia)

Please visit our homepage cmsystemsgroup.com.au.

ConvertFromOldNGs
Posts: 5321
Joined: Wed Aug 05, 2009 5:19 pm

Re: addNoError on the Collection Class

Postby ConvertFromOldNGs » Fri Aug 07, 2009 2:16 pm

by Craig Shearer >> Wed, 14 Jul 1999 0:25:29 GMT

One potential source of errors with this code is deadlock exceptions. The includes method on the collection will place a share lock on itself (and assuming this code executes inside a transaction) will then be upgraded to an exclusive lock for the add operation.

However, if there is another user executing the code at approximately the same time, and both users have the collection share locked at the same time, and both then want to add an object to the collection, then one of the users will encounter a deadlock exception.

A better way to write the code would be:
begin

exclusiveLock(self);
if not self.includes(pMemberType) then
self.add(pMemberType);
endif;
epilog
unlock(self);
end;


Note that in the above situation, contention for the collection will now be handled by the exclusive lock mechanism, which will ensure that only one user at a time can access the collection - the other user will queue, waiting for the other user's exclusive lock to be released.

Note also, that the epilog of the method contains an unlock of the collection. If the collection is persistent, then this isn't strictly necessary, as the collection will be unlocked at the end of the transaction, however, it's there to ensure that the code works for transient collections too.

Craig.

ConvertFromOldNGs
Posts: 5321
Joined: Wed Aug 05, 2009 5:19 pm

Re: addNoError on the Collection Class

Postby ConvertFromOldNGs » Fri Aug 07, 2009 2:16 pm

by Dean Cooper >> Wed, 14 Jul 1999 1:34:11 GMT

Both examples penalise all adds with the cost of an includes, which isn't cheap (particularly for large persistent collections). The includes is guarding against the (hopefully) few cases where an item is already in the collection; for all other cases, it's overhead. Invariably, a more efficient way to do this sort of thing is to use an exception handler. How about the following (with both methods on Collection):

addNoErrorExHandler(e : Exception) : Integer;
constants
ObjectAlreadyInCollection = 1309;begin

if e.errorCode = ObjectAlreadyInCollection then
return Ex_Resume_Next;
endif;
return Ex_Pass_Back;
end;

addNoError(member : MemberType) updating;begin

on Exception do addNoErrorExHandler(exception);
add(member);
end;

This avoids the includes entirely, as well as the contention issues on the collection (well spotted Craig!)

Dean.

ConvertFromOldNGs
Posts: 5321
Joined: Wed Aug 05, 2009 5:19 pm

Re: addNoError on the Collection Class

Postby ConvertFromOldNGs » Fri Aug 07, 2009 2:16 pm

by Craig Shearer >> Wed, 14 Jul 1999 4:22:38 GMT

Good point Dean... though I was interested that you chose to use the 1309 exception code rather than 1310. What is the difference between them?

Craig.

ConvertFromOldNGs
Posts: 5321
Joined: Wed Aug 05, 2009 5:19 pm

Re: addNoError on the Collection Class

Postby ConvertFromOldNGs » Fri Aug 07, 2009 2:16 pm

by Dean Cooper >> Wed, 14 Jul 1999 4:43:00 GMT
Good point Dean... though I was interested that you chose to use the 1309 exception code rather than 1310. What is the difference between them?

1309 means that the object itself is already in the collection (you can get this exception for any type of collection). 1310 means that there is another object in the collection at the same key value (so 1310's can occur only for dictionaries). 1309 is what the 'includes' will guard against. However for a dictionary, even if 'includes' returns false, you could still get a 1310 if you're trying to add a different object with the same key as an existing member.

Dean.


Return to “Tips and Techniques”

Who is online

Users browsing this forum: No registered users and 23 guests