SimpleLock.kl¶
Types¶
AutoLock (struct)¶
Automatically acquires and releases a lock, upon its construction and destruction. The AutoLock is intended to be created as a local variable, whose scope is the same as the need for a lock.
To localize the scope of an AutoLock, add an additional code block:
... thread-safe code ...
{
AutoLock lock( this.myLock );
... thread unsafe code (critical section) ...
}
... thread-safe code ...
Members¶
Ref<SimpleLock> | simpleLock |
SimpleLock (object)¶
The SimpleLock is a simple, reentrant, active-wait mutex designed for protecting access to resources that are locked for a relatively small time. The waiting thread will not return to the scheduler, and wait actively. There is no queue, so starvation is possible under sustained access competition.
The SimpleLock is reentrant, and can be acquired by the same thread multiple times. Acquiring a lock multiple times does incur some overhead, so care should be taken to avoid locking when possible if execution speed is important.
Locking is done by passing a SimpleLock to the following functions: Acquire, Release and TryAcquire. The AutoLock wrapper encapsulates the Acquire and Release of a SimpleLock, which can reduce coding the errors (eg: forgetting to release the lock).
The following facilities might be useful for debugging locking problems:
- A .label member (construction parameter) is used to identify the lock when logging errors or tracing.
- A .maxWaitSeconds member (construction parameter) specifies a maximum delay to get the lock. If that delay is passed:
- If .throwAtMaxWait (construction parameter), an exception will be thrown (default)
- Else, an error statement will get printed
- If the Boolean SimpleLock_trace constant is set to true, each lock and unlock actions will be logged
警告
If an exception is thrown by the thread that locked a lock, the lock will remain in a locked state forever. This applies for AutoLock helper since KL won’t cleanup the stack upon exceptions.
The following example shows using locks to ensure that multiple theads can safely write to the same objectin parallel.
/*
** Example: SimpleLock_simpleTest.kl
*/
require FabricSynchronization;
require Math, Util;
object MyThreadsafeObject {
private SimpleLock lock;
private Integer data[];
};
function MyThreadsafeObject (){
this.lock = SimpleLock("MyThreadsafeObject");
}
function MyThreadsafeObject.setData!(Integer index, Integer value){
// Lock in case data is being modified on a different thread.
AutoLock AL(this.lock);
Count oldSize = this.data.size();
if (index >= oldSize)
this.data.resize(index + 1);
this.data[index] = value;
}
function Integer[] MyThreadsafeObject.getData() {
return this.data;
}
// Add date to the object from multiple threads in parallel.
operator dataData<<<index>>>(io MyThreadsafeObject obj) {
obj.setData(index, mathRandomInteger(675435, index));
}
operator entry() {
MyThreadsafeObject obj();
dataData<<<300>>>(obj);
report(obj.getData());
}
/*
** Output:
[198180864,286336441,123095606,142945287,386507260,142128165,505149650,370787731,354354232,35175377,225549742,264185439,267788980,173254845,78238922,29547115,150288752,415573737,147683878,234466743,50250860,112075349,188197314,223063107,212697000,513853185,376553374,411050511,114321188,292323565,223303610,71932699,52868832,474610713,407522838,479322983,391899868,205988997,488554162,184944371,4439832,183707185,480707982,350376383,290860948,4877597,318226090,469651403,208369744,367174985,364627462,253283607,498603340,123124405,214972322,358864291,403227272,200464737,18902910,22066543,222198788,94399821,499255706,379320443,520781248,17965689,525394422,261712583,65684412,321905893,227218578,230692947,476285432,532865169,455933294,24530207,343952500,358711677,135084170,354260267,227198768,177959849,24682982,123649143,201946668,140878613,483284354,11915011,100341096,231095233,140226398,272505039,223518948,415279533,242764666,465446363,313742496,8493273,115475926,250855975,476884124,214627653,307821170,371194291,230057176,379579121,477857102,265492607,439122260,506521053,534921834,33073803,25896464,34050569,142347718,505641943,262858508,57858933,271188834,18454627,482113608,70446625,295403326,429935663,163894724,157627917,225058138,42476347,358169472,263216953,494254518,469297543,77276540,481318309,310407250,268282643,477384632,430064977,403348782,240169951,118666804,55614013,443472970,191336427,27563248,457113705,188615078,247401271,240412652,102130645,534462786,476524995,109374248,55636097,106422046,97472399,156048036,170267245,210730810,231862427,36975200,397833625,360971670,201384167,70102620,444073477,419001906,456207475,349522584,115470257,156386574,524754751,65733396,22584989,464193066,239224139,185537488,156876489,238458246,143223447,297662668,300432437,148508450,209099555,294415880,322454241,336121598,287515375,379809668,26951373,31486234,343117307,410794304,363584505,92590454,140748871,115099452,297404005,347868178,194149843,118576504,276228625,264928494,420371103,493707252,148959997,193904650,459328171,520266416,326094121,433959270,249207287,127900076,478176405,203320578,522179715,269156584,268494145,203837150,200525391,8377444,173849389,123007738,21298011,459886624,447255129,133182806,242827175,475983900,34494149,415248882,150576947,123760728,477705329,250299598,100558335,72469716,511809373,370280938,396042251,45564304,345582473,447438150,420125015,28396172,259448053,245390050,372956643,406365128,163764129,69754558,446249391,429541700,318932877,451216602,320747707,305362688,197433529,457058614,261728007,409839868,520943397,469624786,255758483,234527544,83939025,237804718,74400095,223365556,450005949,187491274,466175339,526708848,468572649,18323750,309422263,363531116,140748117,425187522,127907651,72177320,76945921,361168542,359365903,413847076,505717741,512272058,483870235,135441888,35122969,31894806,287104615,314601948,273540997,426585522,238637555,387438104,405125425,419857550,112782527]
*/
Members¶
UInt32 | state | internal |
Scalar | secondsBetweenChecks | wait time before checking again, to reduce lock competition (constructor argument) |
Scalar | maxWaitSeconds | wait time before an error is triggered (constructor argument) |
Boolean | throwAtMaxWait | if true, errors will be thrown, else printed (constructor argument) |
String | debugName | Label used for traces or error messages |
Methods¶
SimpleLock ( in SimpleLock other ) | |
SimpleLock ( in String debugName ) | |
SimpleLock ( in String debugName, in Scalar maxWaitSeconds ) | |
SimpleLock ( in String debugName, in Scalar maxWaitSeconds, in Boolean throwAtMaxWait ) | |
SimpleLock ( in String debugName, in Scalar maxWaitSeconds, in Boolean throwAtMaxWait, in Scalar secondsBetweenChecks ) | |
SimpleLock () | |
SimpleLock | clone ? () |
cloneMembersTo ? ( io SimpleLock that ) | |
Boolean | locked ? () |
~SimpleLock () |
Functions¶
TryAcquire¶
Boolean TryAcquire ( in Ref<SimpleLock> simpleLock, in Scalar maxWaitSeconds )
Tries to acquire a lock for maxWaitSeconds
seconds. Will return false
if failed.
TryAcquire¶
Boolean TryAcquire ( in Ref<SimpleLock> simpleLock, in Scalar maxWaitSeconds )
Tries to acquire a lock for maxWaitSeconds
seconds. Will return false
if failed.
Acquire¶
Acquire ( in Ref<SimpleLock> simpleLock, in Scalar maxWaitSeconds )
Acquires a lock. If it takes more than maxWaitSeconds
, an exception is thrown.
Acquire¶
Acquire ( in Ref<SimpleLock> simpleLock, in Scalar maxWaitSeconds )
Acquires a lock. If it takes more than maxWaitSeconds
, an exception is thrown.