diff --git a/native/ios/Comm/TemporalMessageStorage/NonBlockingLock.mm b/native/ios/Comm/TemporalMessageStorage/NonBlockingLock.mm new file mode 100644 --- /dev/null +++ b/native/ios/Comm/TemporalMessageStorage/NonBlockingLock.mm @@ -0,0 +1,70 @@ +#import "NonBlockingLock.h" +#import + +@implementation NonBlockingLock +- (instancetype)initWithName:(NSString *)lockName { + self = [super init]; + if (self) { + _lockName = [lockName cStringUsingEncoding:NSUTF8StringEncoding]; + _lockHandle = nil; + } + return self; +} + +- (BOOL)tryAcquireLock:(NSError **)err { + if (_lockHandle) { + *err = [NSError errorWithDomain:@"app.comm" + code:EBUSY + userInfo:@{ + NSLocalizedDescriptionKey : + @"Attempt to acquire already held lock." + }]; + return NO; + } + sem_t *lock = sem_open(self.lockName, O_CREAT, 0644, 1); + if (lock == SEM_FAILED) { + *err = [NSError errorWithDomain:@"app.comm" + code:errno + userInfo:@{ + NSLocalizedDescriptionKey : [NSString + stringWithCString:strerror(errno) + encoding:NSUTF8StringEncoding] + }]; + sem_close(lock); + return NO; + } + if (sem_trywait(lock)) { + *err = [NSError errorWithDomain:@"app.comm" + code:errno + userInfo:@{ + NSLocalizedDescriptionKey : [NSString + stringWithCString:strerror(errno) + encoding:NSUTF8StringEncoding] + }]; + sem_close(lock); + return NO; + } + _lockHandle = lock; + return YES; +} + +- (void)releaseLock:(NSError **)err { + if (!self.lockHandle) { + *err = + [NSError errorWithDomain:@"app.comm" + code:ENODATA + userInfo:@{ + NSLocalizedDescriptionKey : + @"Attempt to release lock that was not acquired." + }]; + return; + } + sem_post(_lockHandle); + sem_close(_lockHandle); + _lockHandle = nil; +} + +- (void)destroyLock { + sem_unlink(_lockName); +} +@end