summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorxant <xant@xant.net>2013-12-08 11:07:33 (GMT)
committer xant <xant@xant.net>2013-12-08 11:07:33 (GMT)
commitade705491e6a59d0f36e62b3e554e757a323eb60 (patch)
treefd471e8ac14612a0f7af18f7eb64dbb1627ae8b9
parent03ffe7d7ac5a17095dc4ff68a28f7f25d40368e1 (diff)
using OSSpinLock instead of NSLock gains in performances
especially for the nature of such locks
-rw-r--r--core/JMXAudioDevice.m35
-rw-r--r--core/JMXAudioFile.h11
-rw-r--r--core/JMXAudioFile.m58
-rw-r--r--core/JMXDrawPath.h17
-rw-r--r--core/JMXDrawPath.mm84
-rw-r--r--core/JMXEntity.h3
-rw-r--r--core/JMXInputPin.h6
-rw-r--r--core/JMXInputPin.m103
-rw-r--r--core/JMXOutputPin.h5
-rw-r--r--core/JMXOutputPin.m47
-rw-r--r--core/JMXPin.h7
-rw-r--r--core/JMXPin.mm37
-rw-r--r--entities/JMXAudioCapture.mm7
-rw-r--r--entities/JMXAudioOutput.mm89
-rw-r--r--entities/JMXAudioSpectrumAnalyzer.mm102
-rw-r--r--entities/JMXDrawEntity.h6
-rw-r--r--entities/JMXDrawEntity.mm50
-rw-r--r--entities/JMXVideoOutput.mm47
-rw-r--r--entities/video_filters/JMXCoreImageFilter.mm62
-rw-r--r--entities/video_outputs/JMXOpenGLScreen.mm47
-rw-r--r--gui/JMXCodePanel.m58
21 files changed, 428 insertions, 453 deletions
diff --git a/core/JMXAudioDevice.m b/core/JMXAudioDevice.m
index fc570b4..69d9791 100644
--- a/core/JMXAudioDevice.m
+++ b/core/JMXAudioDevice.m
@@ -1428,27 +1428,28 @@ finish:
outputData:(AudioBufferList *)outOutputData
outputTime:(AudioTimeStamp *)inOutputTime
{
+ static OSSpinLock lock;
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- @synchronized(self) {
- if ( isPaused )
- return;
+ OSSpinLockLock(&lock);
+ if ( isPaused )
+ return;
#if 0
- if (myIOProc)
- {
- (void)(*myIOProc)( myDevice, inNow, inInputData, inInputTime, outOutputData, inOutputTime, myIOProcClientData );
- }
- else
+ if (myIOProc)
+ {
+ (void)(*myIOProc)( myDevice, inNow, inInputData, inInputTime, outOutputData, inOutputTime, myIOProcClientData );
+ }
+ else
#endif
- if (myIOInvocation)
- {
- [myIOInvocation setArgument:&inNow atIndex:3];
- [myIOInvocation setArgument:&inInputData atIndex:4];
- [myIOInvocation setArgument:&inInputTime atIndex:5];
- [myIOInvocation setArgument:&outOutputData atIndex:6];
- [myIOInvocation setArgument:&inOutputTime atIndex:7];
- [myIOInvocation invoke];
- }
+ if (myIOInvocation)
+ {
+ [myIOInvocation setArgument:&inNow atIndex:3];
+ [myIOInvocation setArgument:&inInputData atIndex:4];
+ [myIOInvocation setArgument:&inInputTime atIndex:5];
+ [myIOInvocation setArgument:&outOutputData atIndex:6];
+ [myIOInvocation setArgument:&inOutputTime atIndex:7];
+ [myIOInvocation invoke];
}
+ OSSpinLockUnlock(&lock);
[pool drain];
}
diff --git a/core/JMXAudioFile.h b/core/JMXAudioFile.h
index 5244c9a..929a690 100644
--- a/core/JMXAudioFile.h
+++ b/core/JMXAudioFile.h
@@ -39,16 +39,7 @@
Note that all samples will be returned as :
44100 float32 stereo interleaved
*/
-@interface JMXAudioFile : NSObject {
-@private
- ExtAudioFileRef audioFile;
- AudioStreamBasicDescription fileFormat;
- JMXAudioBuffer *samples[kJMXAudioFileBufferCount];
- UInt32 rOffset;
- UInt32 wOffset;
- BOOL isFilling;
- NSURL *url;
-}
+@interface JMXAudioFile : NSObject
@property (copy) NSURL *url;
/*!
diff --git a/core/JMXAudioFile.m b/core/JMXAudioFile.m
index cffb429..0fbe084 100644
--- a/core/JMXAudioFile.m
+++ b/core/JMXAudioFile.m
@@ -24,6 +24,18 @@
#import "JMXAudioFile.h"
#import "JMXAudioBuffer.h"
+@interface JMXAudioFile () {
+ ExtAudioFileRef audioFile;
+ AudioStreamBasicDescription fileFormat;
+ JMXAudioBuffer *samples[kJMXAudioFileBufferCount];
+ OSSpinLock lock;
+ UInt32 rOffset;
+ UInt32 wOffset;
+ BOOL isFilling;
+ NSURL *url;
+ BOOL overflow;
+}
+@end
@implementation JMXAudioFile
@synthesize url;
@@ -43,20 +55,22 @@
// in the worst case we will do an extra iteration ...
// which is not a big deal (having a long-term lock is much worse)
//NSLog(@"%@ buffering starts", self.url );
- while (wOffset-rOffset < kJMXAudioFileBufferCount/2) {
- @synchronized(self) {
- JMXAudioBuffer *newSample = [self readFrames:512];
- if (samples[wOffset%kJMXAudioFileBufferCount]) {
- [samples[wOffset%kJMXAudioFileBufferCount] release];
- samples[wOffset%kJMXAudioFileBufferCount] = nil;
- }
- if (newSample) {
- samples[wOffset++%kJMXAudioFileBufferCount] = [newSample retain];
- } else {
- // end of file
- break;
- }
+ BOOL eof = NO;
+ while (wOffset-rOffset < kJMXAudioFileBufferCount/2 && !eof) {
+ JMXAudioBuffer *newSample = [self readFrames:512];
+ OSSpinLockLock(&lock);
+ if (samples[wOffset%kJMXAudioFileBufferCount]) {
+ [samples[wOffset%kJMXAudioFileBufferCount] release];
+ samples[wOffset%kJMXAudioFileBufferCount] = nil;
}
+ if (newSample) {
+ samples[wOffset++%kJMXAudioFileBufferCount] = [newSample retain];
+ if (wOffset == 0)
+ overflow = YES;
+ } else {
+ eof = YES;
+ }
+ OSSpinLockUnlock(&lock);
}
//NSLog(@"%@ buffering ends", self.url);
isFilling = NO;
@@ -115,16 +129,20 @@
- (JMXAudioBuffer *)readSample
{
JMXAudioBuffer *sample = nil;
- @synchronized(self) {
+ OSSpinLockLock(&lock);
+ if (rOffset < wOffset || overflow) {
sample = samples[rOffset%kJMXAudioFileBufferCount];
samples[rOffset++%kJMXAudioFileBufferCount] = nil;
- if (wOffset - rOffset < kJMXAudioFileBufferCount / 4 && !isFilling &&
- !(self.currentOffset >= self.numFrames - (512 * self.numChannels)))
- {
- isFilling = YES;
- [self performSelectorInBackground:@selector(fillBuffer) withObject:nil];
- }
+ if (rOffset == 0 && overflow) // Note: rOffset is always behind wOffset
+ overflow = NO;
+ }
+ if ((wOffset <= rOffset || wOffset - rOffset < kJMXAudioFileBufferCount / 4) && !overflow
+ && !isFilling && !(self.currentOffset >= self.numFrames - (512 * self.numChannels)))
+ {
+ isFilling = YES;
+ [self performSelectorInBackground:@selector(fillBuffer) withObject:nil];
}
+ OSSpinLockUnlock(&lock);
return [sample autorelease];
}
diff --git a/core/JMXDrawPath.h b/core/JMXDrawPath.h
index 14baf32..6101483 100644
--- a/core/JMXDrawPath.h
+++ b/core/JMXDrawPath.h
@@ -37,23 +37,6 @@
CIImage *currentFrame;
id<JMXCanvasStyle,JMXV8> fillStyle;
id<JMXCanvasStyle,JMXV8> strokeStyle;
-@private
- JMXSize *frameSize;
- BOOL _clear;
- NSUInteger subPaths;
- double globalAlpha;
- NSString *globalCompositeOperation;
- NSFont *font;
- CGFloat lineWidth;
- //BOOL _needsRender;
- BOOL _didFill;
- BOOL _didStroke;
- BOOL invertYCoordinates;
- NSColor *shadowColor;
- CGFloat shadowOffsetX;
- CGFloat shadowOffsetY;
- CGFloat shadowBlur;
- CGPathRef lastPath;
}
/*!
diff --git a/core/JMXDrawPath.mm b/core/JMXDrawPath.mm
index f528708..e79840a 100644
--- a/core/JMXDrawPath.mm
+++ b/core/JMXDrawPath.mm
@@ -26,7 +26,25 @@ using namespace v8;
#pragma mark JMXDrawPath
-@interface JMXDrawPath ()
+@interface JMXDrawPath () {
+ JMXSize *frameSize;
+ BOOL _clear;
+ NSUInteger subPaths;
+ double globalAlpha;
+ NSString *globalCompositeOperation;
+ NSFont *font;
+ CGFloat lineWidth;
+ //BOOL _needsRender;
+ BOOL _didFill;
+ BOOL _didStroke;
+ BOOL invertYCoordinates;
+ NSColor *shadowColor;
+ CGFloat shadowOffsetX;
+ CGFloat shadowOffsetY;
+ CGFloat shadowBlur;
+ CGPathRef lastPath;
+ OSSpinLock lock;
+}
@property (retain) CIImage *currentFrame;
@end
@@ -797,34 +815,34 @@ using namespace v8;
- (void)doRender
{
- @synchronized(self) {
- UInt32 pathIndex = pathLayerOffset%kJMXDrawPathBufferCount;
+ OSSpinLockLock(&lock);
+ UInt32 pathIndex = pathLayerOffset%kJMXDrawPathBufferCount;
- #if 0
- CGContextRef context = CGLayerGetContext(pathLayers[pathIndex]);
+#if 0
+ CGContextRef context = CGLayerGetContext(pathLayers[pathIndex]);
- BOOL fillOrStroke = (_didFill || _didStroke);
- CGPathDrawingMode drawingMode = kCGPathFillStroke;
- if (fillOrStroke && !(_didFill && _didStroke)) {
- if (_didFill)
- drawingMode = kCGPathFill;
- else if (_didStroke)
- drawingMode = kCGPathStroke;
- }
- if (fillOrStroke) {
- _didFill = _didStroke = NO;
- CGContextDrawPath(context, drawingMode);
- }
- #endif
-
- //if (_needsRender) {
- [self clearFrame:NO];
- self.currentFrame = [CIImage imageWithCGLayer:pathLayers[pathIndex]];
- //_needsRender = NO;
- _didStroke = NO;
- _didFill = NO;
- //}
+ BOOL fillOrStroke = (_didFill || _didStroke);
+ CGPathDrawingMode drawingMode = kCGPathFillStroke;
+ if (fillOrStroke && !(_didFill && _didStroke)) {
+ if (_didFill)
+ drawingMode = kCGPathFill;
+ else if (_didStroke)
+ drawingMode = kCGPathStroke;
+ }
+ if (fillOrStroke) {
+ _didFill = _didStroke = NO;
+ CGContextDrawPath(context, drawingMode);
}
+#endif
+
+ //if (_needsRender) {
+ [self clearFrame:NO];
+ self.currentFrame = [CIImage imageWithCGLayer:pathLayers[pathIndex]];
+ //_needsRender = NO;
+ _didStroke = NO;
+ _didFill = NO;
+ //}
+ OSSpinLockUnlock(&lock);
}
static NSString *validCompositeOperations[] = {
@@ -845,18 +863,20 @@ static NSString *validCompositeOperations[] = {
- (NSString *)globalCompositeOperation
{
- @synchronized(self) {
- return [[globalCompositeOperation retain] autorelease];
- }
+ NSString *string;
+ OSSpinLockLock(&lock);
+ string = [[globalCompositeOperation retain] autorelease];
+ OSSpinLockUnlock(&lock);
+ return string;
}
- (void)setGlobalCompositeOperation:(NSString *)operation
{
for (int i = 0; validCompositeOperations[i]; i++) {
if ([operation caseInsensitiveCompare:validCompositeOperations[i]] == NSOrderedSame) {
- @synchronized(self) {
- globalCompositeOperation = [validCompositeOperations[i] copy];
- }
+ OSSpinLockLock(&lock);
+ globalCompositeOperation = [validCompositeOperations[i] copy];
+ OSSpinLockUnlock(&lock);
break;
}
}
diff --git a/core/JMXEntity.h b/core/JMXEntity.h
index 0a0ed03..b24c02c 100644
--- a/core/JMXEntity.h
+++ b/core/JMXEntity.h
@@ -84,6 +84,7 @@
@public
NSString *label;
BOOL active;
+
@protected
/*
NSMutableDictionary *inputPins;
@@ -93,6 +94,8 @@
JMXInputPin *activeIn;
JMXOutputPin *activeOut;
NSMutableSet *proxyPins;
+ OSSpinLock lock;
+
@private
NSMutableDictionary *privateData;
JMXEntity *owner;
diff --git a/core/JMXInputPin.h b/core/JMXInputPin.h
index 0e41721..3a40e34 100644
--- a/core/JMXInputPin.h
+++ b/core/JMXInputPin.h
@@ -34,10 +34,8 @@
@class JMXInputPin
@abstract concrete class for input pins
*/
-@interface JMXInputPin : JMXPin {
- NSMutableArray *producers;
- int passiveProducersCount;
-}
+@interface JMXInputPin : JMXPin
+
/*!
@property producers
@abstract array containing all output pins currently connected to this input pin
diff --git a/core/JMXInputPin.m b/core/JMXInputPin.m
index d72721c..705556a 100644
--- a/core/JMXInputPin.m
+++ b/core/JMXInputPin.m
@@ -25,6 +25,15 @@
#import "JMXOutputPin.h"
#import "JMXAttribute.h"
+@interface JMXInputPin ()
+{
+ NSMutableArray *producers;
+ int passiveProducersCount;
+ OSSpinLock producersLock;
+}
+
+@end
+
@implementation JMXInputPin
@synthesize producers;
@@ -61,13 +70,13 @@
- (NSArray *)readProducers
{
NSMutableArray *array = [[NSMutableArray alloc] init];
- @synchronized(producers) {
- for (JMXOutputPin *producer in producers) {
- id value = [producer readData];
- if (value)
- [array addObject:value];
- }
+ OSSpinLockLock(&producersLock);
+ for (JMXOutputPin *producer in producers) {
+ id value = [producer readData];
+ if (value)
+ [array addObject:value];
}
+ OSSpinLockUnlock(&producersLock);
return [array autorelease];
}
@@ -83,40 +92,40 @@
- (BOOL)moveProducerFromIndex:(NSUInteger)src toIndex:(NSUInteger)dst
{
- @synchronized(producers) {
- if ([producers count] > dst) {
- JMXOutputPin *obj = [[producers objectAtIndex:src] retain];
- [producers removeObjectAtIndex:src];
- [producers insertObject:obj atIndex:dst];
- [obj release];
- return YES;
- }
+ OSSpinLockLock(&producersLock);
+ if ([producers count] > dst) {
+ JMXOutputPin *obj = [[producers objectAtIndex:src] retain];
+ [producers removeObjectAtIndex:src];
+ [producers insertObject:obj atIndex:dst];
+ [obj release];
+ return YES;
}
+ OSSpinLockUnlock(&producersLock);
return NO;
}
- (BOOL)connectToPin:(JMXOutputPin *)destinationPin
{
if ([self canConnectToPin:destinationPin]) {
- @synchronized(producers) {
- if ([producers count] && !multiple) {
- JMXOutputPin *producer = [producers objectAtIndex:0];
- [producer detachObject:self];
- [super disconnectFromPin:producer];
- if (producer.mode == kJMXPinModePassive)
- passiveProducersCount--;
- [producers removeObjectAtIndex:0];
- }
- if ([destinationPin attachObject:self withSelector:@"deliverData:fromSender:"]) {
- [producers addObject:destinationPin];
- connected = YES;
- NSXMLNode *connectedAttribute = [self attributeForName:@"connected"];
- [connectedAttribute setStringValue:@"YES"];
- if (destinationPin.mode == kJMXPinModePassive)
- passiveProducersCount++;
- return [super connectToPin:destinationPin];
- }
+ OSSpinLockLock(&producersLock);
+ if ([producers count] && !multiple) {
+ JMXOutputPin *producer = [producers objectAtIndex:0];
+ [producer detachObject:self];
+ [super disconnectFromPin:producer];
+ if (producer.mode == kJMXPinModePassive)
+ passiveProducersCount--;
+ [producers removeObjectAtIndex:0];
+ }
+ if ([destinationPin attachObject:self withSelector:@"deliverData:fromSender:"]) {
+ [producers addObject:destinationPin];
+ connected = YES;
+ NSXMLNode *connectedAttribute = [self attributeForName:@"connected"];
+ [connectedAttribute setStringValue:@"YES"];
+ if (destinationPin.mode == kJMXPinModePassive)
+ passiveProducersCount++;
+ return [super connectToPin:destinationPin];
}
+ OSSpinLockUnlock(&producersLock);
}
return NO;
}
@@ -124,17 +133,17 @@
- (void)disconnectFromPin:(JMXOutputPin *)destinationPin
{
[destinationPin retain];
- @synchronized(producers) {
- [producers removeObjectIdenticalTo:destinationPin];
- [destinationPin detachObject:self];
- if (destinationPin.mode == kJMXPinModePassive)
- passiveProducersCount--;
- if ([producers count] == 0) {
- NSXMLNode *connectedAttribute = [self attributeForName:@"connected"];
- [connectedAttribute setStringValue:@"NO"];
- connected = NO;
- }
+ OSSpinLockLock(&producersLock);
+ [producers removeObjectIdenticalTo:destinationPin];
+ [destinationPin detachObject:self];
+ if (destinationPin.mode == kJMXPinModePassive)
+ passiveProducersCount--;
+ if ([producers count] == 0) {
+ NSXMLNode *connectedAttribute = [self attributeForName:@"connected"];
+ [connectedAttribute setStringValue:@"NO"];
+ connected = NO;
}
+ OSSpinLockUnlock(&producersLock);
for (NSXMLElement *element in connections.children) {
if ([[element attributeForName:@"uid"] isEqual:[destinationPin attributeForName:@"uid"]]) {
@@ -156,11 +165,11 @@
- (void)disconnectAllPins
{
- @synchronized(producers) {
- while ([producers count])
- [self disconnectFromPin:[producers objectAtIndex:0]];
- passiveProducersCount = 0;
- }
+ OSSpinLockLock(&producersLock);
+ while ([producers count])
+ [self disconnectFromPin:[producers objectAtIndex:0]];
+ passiveProducersCount = 0;
+ OSSpinLockUnlock(&producersLock);
}
/*
diff --git a/core/JMXOutputPin.h b/core/JMXOutputPin.h
index b59d968..5f8a4bf 100644
--- a/core/JMXOutputPin.h
+++ b/core/JMXOutputPin.h
@@ -34,10 +34,7 @@
@class JMXOutputPin
@abstract concrete class for output pins
*/
-@interface JMXOutputPin : JMXPin {
- NSMutableDictionary *receivers;
-
-}
+@interface JMXOutputPin : JMXPin
/*!
@property receivers
diff --git a/core/JMXOutputPin.m b/core/JMXOutputPin.m
index 9d27e9a..f654738 100644
--- a/core/JMXOutputPin.m
+++ b/core/JMXOutputPin.m
@@ -31,6 +31,13 @@
- (void)sendData:(id)data toReceiver:(id)receiver withSelector:(NSString *)selectorName fromSender:(id)sender;
@end
+@interface JMXOutputPin ()
+{
+ NSMutableDictionary *receivers;
+ OSSpinLock receiversLock;
+}
+@end
+
@implementation JMXOutputPin
@synthesize receivers;
@@ -68,14 +75,14 @@
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[super performSignal:signal];
// and then propagate it to all receivers
- @synchronized (receivers) {
- for (id receiver in [receivers allKeys]) {
- signal.receiver = receiver;
- [self sendData:signal.data toReceiver:receiver
- withSelector:[receivers objectForKey:receiver]
- fromSender:signal.sender];
- }
+ OSSpinLockLock(&receiversLock);
+ for (id receiver in [receivers allKeys]) {
+ signal.receiver = receiver;
+ [self sendData:signal.data toReceiver:receiver
+ withSelector:[receivers objectForKey:receiver]
+ fromSender:signal.sender];
}
+ OSSpinLockUnlock(&receiversLock);
[pool drain];
}
@@ -100,9 +107,9 @@
[newConnection addAttribute:[JMXAttribute attributeWithName:@"entity" stringValue:[self.owner uid]]];
[destinationPin.connections addChild:newConnection];
}
- @synchronized(receivers) {
- [receivers setObject:pinSignal forKey:pinReceiver];
- }
+ OSSpinLockLock(&receiversLock);
+ [receivers setObject:pinSignal forKey:pinReceiver];
+ OSSpinLockUnlock(&receiversLock);
rv = YES;
// deliver the signal to the just connected receiver
if (rv == YES) {
@@ -126,14 +133,14 @@
- (void)detachObject:(id)pinReceiver
{
- @synchronized(receivers) {
- [receivers removeObjectForKey:pinReceiver];
- if ([receivers count] == 0) {
- connected = NO;
- NSXMLNode *connectedAttribute = [self attributeForName:@"connected"];
- [connectedAttribute setStringValue:@"NO"];
- }
+ OSSpinLockLock(&receiversLock);
+ [receivers removeObjectForKey:pinReceiver];
+ if ([receivers count] == 0) {
+ connected = NO;
+ NSXMLNode *connectedAttribute = [self attributeForName:@"connected"];
+ [connectedAttribute setStringValue:@"NO"];
}
+ OSSpinLockUnlock(&receiversLock);
}
// disconnection (as well as connection) happens always from the input pin to the output one
@@ -151,9 +158,9 @@
- (void)disconnectAllPins
{
NSArray *receiverObjects;
- @synchronized(receivers) {
- receiverObjects = [receivers allKeys];
- }
+ OSSpinLockLock(&receiversLock);
+ receiverObjects = [receivers allKeys];
+ OSSpinLockUnlock(&receiversLock);
for (JMXPin *receiver in receiverObjects)
[receiver disconnectFromPin:self];
}
diff --git a/core/JMXPin.h b/core/JMXPin.h
index 4ccf115..a9ebc54 100644
--- a/core/JMXPin.h
+++ b/core/JMXPin.h
@@ -138,13 +138,6 @@ typedef enum {
NSMutableArray *allowedValues;
NSXMLElement *connections;
JMXPinMode mode;
-@private
- JMXPinReadMode readMode;
- SEL readSignal;
- id dataBuffer[kJMXPinDataBufferMask+1]; // double buffer synchronized for writers
- // but lockless for readers
- volatile int32_t offset;
-
}
/*!
diff --git a/core/JMXPin.mm b/core/JMXPin.mm
index 3e94985..7a963a2 100644
--- a/core/JMXPin.mm
+++ b/core/JMXPin.mm
@@ -35,6 +35,17 @@
#import <libkern/OSAtomic.h>
using namespace v8;
+@interface JMXPin ()
+{
+ JMXPinReadMode readMode;
+ SEL readSignal;
+ id dataBuffer[kJMXPinDataBufferMask+1]; // double buffer synchronized for writers
+ // but lockless for readers
+ volatile int32_t offset;
+ OSSpinLock lock;
+}
+@end
+
@implementation JMXPin
@synthesize type, label, multiple, continuous, connected, sendNotifications,
@@ -365,9 +376,9 @@ using namespace v8;
- (void)dealloc
{
- @synchronized(self) {
- [self performSelectorOnMainThread:@selector(notifyRelease) withObject:nil waitUntilDone:YES];
- }
+ OSSpinLockLock(&lock);
+ [self performSelectorOnMainThread:@selector(notifyRelease) withObject:nil waitUntilDone:YES];
+ OSSpinLockUnlock(&lock);
[connections detach];
[connections release];
[label release];
@@ -610,10 +621,10 @@ using namespace v8;
currentSender = self;
JMXPinSignal *signal = nil;
- @synchronized(self) {
- if (owner)
- signal = [JMXPinSignal signalFromSender:sender receiver:owner data:data];
- }
+ OSSpinLockLock(&lock);
+ if (owner)
+ signal = [JMXPinSignal signalFromSender:sender receiver:owner data:data];
+ OSSpinLockUnlock(&lock);
#if USE_NSOPERATIONS
NSBlockOperation *signalDelivery = [NSBlockOperation blockOperationWithBlock:^{
@@ -681,12 +692,12 @@ using namespace v8;
- (void)detach
{
- @synchronized(self) {
- owner = nil;
- if (ownerSignal)
- [ownerSignal release];
- ownerSignal = nil;
- }
+ OSSpinLockLock(&lock);
+ owner = nil;
+ if (ownerSignal)
+ [ownerSignal release];
+ ownerSignal = nil;
+ OSSpinLockUnlock(&lock);
[super detach];
}
diff --git a/entities/JMXAudioCapture.mm b/entities/JMXAudioCapture.mm
index 5a07c31..9ca4474 100644
--- a/entities/JMXAudioCapture.mm
+++ b/entities/JMXAudioCapture.mm
@@ -68,10 +68,11 @@
- (JMXAudioBuffer *)currentBuffer
{
+ static OSSpinLock lock;
JMXAudioBuffer *buf = nil;
- @synchronized (self) {
- buf = [[currentBuffer retain] autorelease];
- }
+ OSSpinLockLock(&lock);
+ buf = [[currentBuffer retain] autorelease];
+ OSSpinLockUnlock(&lock);
return buf;
}
diff --git a/entities/JMXAudioOutput.mm b/entities/JMXAudioOutput.mm
index cc2a1f1..879ecda 100644
--- a/entities/JMXAudioOutput.mm
+++ b/entities/JMXAudioOutput.mm
@@ -84,89 +84,14 @@ static OSStatus _FillComplexBufferProc (
if (!buffer)
return;
-#if 0 // disable conversion for now
- // sample needs to be converted before being sent to the audio device
- // the output format depends on the output device and could be different from the
- // one used internally (44Khz stereo float32 interleaved)
-
- AudioStreamBasicDescription inputDescription = buffer.format.audioStreamBasicDescription;
- if (!converter) { // create on first use
- if ( noErr != AudioConverterNew ( &inputDescription, &outputDescription, &converter )) {
- converter = NULL; // just in case
- // TODO - Error Messages
- return;
- } else {
-
- UInt32 primeMethod = kConverterPrimeMethod_None;
- UInt32 srcQuality = kAudioConverterQuality_Max;
- (void) AudioConverterSetProperty ( converter, kAudioConverterPrimeMethod, sizeof(UInt32), &primeMethod );
- (void) AudioConverterSetProperty ( converter, kAudioConverterSampleRateConverterQuality, sizeof(UInt32), &srcQuality );
- }
- } else {
- // TODO - check if inputdescription or outputdescription have changed and,
- // if that's the case, reset the converter accordingly
- }
- OSStatus err = noErr;
- CallbackContext callbackContext;
- UInt32 framesRead = [buffer numFrames];
- // TODO - check if framesRead is > 512
- outputBufferList->mBuffers[0].mDataByteSize = outputDescription.mBytesPerFrame * outputDescription.mChannelsPerFrame * framesRead;
- outputBufferList->mBuffers[0].mData = convertedBuffer+(convertedOffset++%kJMXAudioOutputConvertedBufferSize)*chunkSize;
- callbackContext.theConversionBuffer = buffer;
- callbackContext.wait = NO; // XXX (actually unused)
- //UInt32 outputChannels = [buffer numChannels];
- if (inputDescription.mSampleRate == outputDescription.mSampleRate &&
- inputDescription.mBytesPerFrame == outputDescription.mBytesPerFrame) {
- err = AudioConverterConvertBuffer (
- converter,
- buffer.bufferList->mBuffers[0].mDataByteSize,
- buffer.bufferList->mBuffers[0].mData,
- &outputBufferList->mBuffers[0].mDataByteSize,
- outputBufferList->mBuffers[0].mData
- );
- } else {
- err = AudioConverterFillComplexBuffer ( converter, _FillComplexBufferProc, &callbackContext, &framesRead, outputBufferList, NULL );
- }
- if (err != noErr) {
- JMXAudioBuffer *previousSample;
- @synchronized(samples) {
- previousSample = samples[wOffset%kJMXAudioOutputSamplesBufferCount];
- samples[wOffset++%kJMXAudioOutputSamplesBufferCount] = [[JMXAudioBuffer audioBufferWithCoreAudioBufferList:outputBufferList andFormat:&inputDescription copy:YES freeOnRelease:YES] retain];
- }
- // let's have the buffer released next time the active pool is drained
- // we want to return as soon as possible
- if (previousSample)
- [previousSample release];
- }
-#else
- JMXAudioBuffer *previousSample;
- previousSample = samples[wOffset%kJMXAudioOutputSamplesBufferCount];
- samples[(wOffset+1)%kJMXAudioOutputSamplesBufferCount] = [buffer retain];
- OSAtomicIncrement32(&wOffset);
- // let's have the buffer released next time the active pool is drained
- // we want to return as soon as possible
- if (previousSample)
- [previousSample release];
-#endif
+
[currentSamplePin deliverData:buffer fromSender:self];
- if (wOffset > kJMXAudioOutputSamplesBufferPrefillCount)
- needsPrefill = NO;
}
// this will only be called by the audio-output mainthread
// so we can avoid using locks
- (JMXAudioBuffer *)currentSample
{
-#if 0
- //NSLog(@"r: %d - w: %d", rOffset % kJMXAudioOutputSamplesBufferCount , wOffset % kJMXAudioOutputSamplesBufferCount);
- JMXAudioBuffer *sample = nil;
- if (rOffset < wOffset && !needsPrefill) {
- sample = samples[rOffset%kJMXAudioOutputSamplesBufferCount];
- samples[(rOffset+1)%kJMXAudioOutputSamplesBufferCount] = nil;
- OSAtomicIncrement32(&rOffset);
- }
- return [sample autorelease];
-#else
JMXAudioBuffer *buffer = audioInputPin.data;
// sample needs to be converted before being sent to the audio device
// the output format depends on the output device and could be different from the
@@ -212,22 +137,10 @@ static OSStatus _FillComplexBufferProc (
err = AudioConverterFillComplexBuffer ( converter, _FillComplexBufferProc, &callbackContext, &framesRead, outputBufferList, NULL );
}
if (err != noErr) {
- /*
- JMXAudioBuffer *previousSample;
- @synchronized(samples) {
- previousSample = samples[wOffset%kJMXAudioOutputSamplesBufferCount];
- samples[wOffset++%kJMXAudioOutputSamplesBufferCount] = [[JMXAudioBuffer audioBufferWithCoreAudioBufferList:outputBufferList andFormat:&inputDescription copy:YES freeOnRelease:YES] retain];
- }
- // let's have the buffer released next time the active pool is drained
- // we want to return as soon as possible
- if (previousSample)
- [previousSample release];
- */
}
JMXAudioBuffer *outputBuffer = [JMXAudioBuffer audioBufferWithCoreAudioBufferList:outputBufferList andFormat:&outputDescription];
currentSamplePin.data = outputBuffer;
return outputBuffer;
-#endif
}
- (void)dealloc
diff --git a/entities/JMXAudioSpectrumAnalyzer.mm b/entities/JMXAudioSpectrumAnalyzer.mm
index 4db7583..7706165 100644
--- a/entities/JMXAudioSpectrumAnalyzer.mm
+++ b/entities/JMXAudioSpectrumAnalyzer.mm
@@ -164,66 +164,70 @@ static int _defaultFrequencies[kJMXAudioSpectrumNumFrequencies] =
{
if (!sample)
return;
+
+ static OSSpinLock lock;
// XXX - get rid of this stupid lock
- @synchronized(analyzer) {
- AudioBufferList *bufferList = sample.bufferList;
- switch(bufferList->mNumberBuffers) {
- case 1:
- switch (bufferList->mBuffers[0].mNumberChannels) {
- case 1: // we got a mono sample, let's just copy that across all channels
- for (int i = 0; i < deinterleavedBuffer->mNumberBuffers; i++) {
- UInt32 sizeToCopy = MIN(bufferList->mBuffers[0].mDataByteSize,
- deinterleavedBuffer->mBuffers[i].mDataByteSize);
- memcpy(deinterleavedBuffer->mBuffers[i].mData, bufferList->mBuffers[0].mData, sizeToCopy);
- }
- break;
- case 2:
- {
- UInt32 numFrames = (UInt32)[sample numFrames];
- for (int j = 0; j < numFrames; j++) {
- uint8_t *frame = ((uint8_t *)bufferList->mBuffers[0].mData) + (j*8);
- memcpy((u_char *)deinterleavedBuffer->mBuffers[0].mData+(j*4), frame, 4);
- memcpy((u_char *)deinterleavedBuffer->mBuffers[1].mData+(j*4), frame + 4, 4);
- }
- }
- break;
- default: // more than 2 channels are not supported yet
- // TODO - error messages
- return;
- }
- break;
- case 2: // same number of channels (2 at the moment)
+ OSSpinLockLock(&lock);
+ AudioBufferList *bufferList = sample.bufferList;
+ switch(bufferList->mNumberBuffers) {
+ case 1:
+ switch (bufferList->mBuffers[0].mNumberChannels) {
+ case 1: // we got a mono sample, let's just copy that across all channels
for (int i = 0; i < deinterleavedBuffer->mNumberBuffers; i++) {
- UInt32 sizeToCopy = MIN(bufferList->mBuffers[i].mDataByteSize,
+ UInt32 sizeToCopy = MIN(bufferList->mBuffers[0].mDataByteSize,
deinterleavedBuffer->mBuffers[i].mDataByteSize);
- memcpy(deinterleavedBuffer->mBuffers[i].mData, bufferList->mBuffers[i].mData, sizeToCopy);
+ memcpy(deinterleavedBuffer->mBuffers[i].mData, bufferList->mBuffers[0].mData, sizeToCopy);
+ }
+ break;
+ case 2:
+ {
+ UInt32 numFrames = (UInt32)[sample numFrames];
+ for (int j = 0; j < numFrames; j++) {
+ uint8_t *frame = ((uint8_t *)bufferList->mBuffers[0].mData) + (j*8);
+ memcpy((u_char *)deinterleavedBuffer->mBuffers[0].mData+(j*4), frame, 4);
+ memcpy((u_char *)deinterleavedBuffer->mBuffers[1].mData+(j*4), frame + 4, 4);
+ }
}
break;
- default: // buffers with more than 2 channels are not supported yet
+ default: // more than 2 channels are not supported yet
// TODO - error messages
+ OSSpinLockUnlock(&lock);
return;
}
- [analyzer processForwards:(UInt32)[sample numFrames] input:deinterleavedBuffer];
+ break;
+ case 2: // same number of channels (2 at the moment)
+ for (int i = 0; i < deinterleavedBuffer->mNumberBuffers; i++) {
+ UInt32 sizeToCopy = MIN(bufferList->mBuffers[i].mDataByteSize,
+ deinterleavedBuffer->mBuffers[i].mDataByteSize);
+ memcpy(deinterleavedBuffer->mBuffers[i].mData, bufferList->mBuffers[i].mData, sizeToCopy);
+ }
+ break;
+ default: // buffers with more than 2 channels are not supported yet
+ // TODO - error messages
+ OSSpinLockUnlock(&lock);
+ return;
+ }
+ [analyzer processForwards:(UInt32)[sample numFrames] input:deinterleavedBuffer];
- [analyzer getMagnitude:spectrumBuffer min:minAmp max:maxAmp];
+ [analyzer getMagnitude:spectrumBuffer min:minAmp max:maxAmp];
+
+ for (UInt32 i = 0; i < kJMXAudioSpectrumNumFrequencies; i++) { // for each frequency
+ int freq = [[frequencies objectAtIndex:i] intValue];
+ int offset = freq*numBins/44100*analyzer.numChannels;
+ Float32 freqValue = (((Float32 *)(spectrumBuffer->mBuffers[0].mData))[offset] +
+ ((Float32 *)(spectrumBuffer->mBuffers[1].mData))[offset]) * 0.5;
+ if (freqValue < 0.0)
+ freqValue = 0.0;
- for (UInt32 i = 0; i < kJMXAudioSpectrumNumFrequencies; i++) { // for each frequency
- int freq = [[frequencies objectAtIndex:i] intValue];
- int offset = freq*numBins/44100*analyzer.numChannels;
- Float32 freqValue = (((Float32 *)(spectrumBuffer->mBuffers[0].mData))[offset] +
- ((Float32 *)(spectrumBuffer->mBuffers[1].mData))[offset]) * 0.5;
- if (freqValue < 0.0)
- freqValue = 0.0;
-
- NSNumber *numberValue = [NSNumber numberWithFloat:freqValue];
- [(JMXOutputPin *)[frequencyPins objectAtIndex:i] deliverData:numberValue];
- frequencyValues[i] = freqValue;
- }
- if (runcycleCount%5 == 0 && imagePin.connected) { // draw the image only once every 10 samples
- [self drawSpectrumImage];
- }
- runcycleCount++;
+ NSNumber *numberValue = [NSNumber numberWithFloat:freqValue];
+ [(JMXOutputPin *)[frequencyPins objectAtIndex:i] deliverData:numberValue];
+ frequencyValues[i] = freqValue;
+ }
+ if (runcycleCount%5 == 0 && imagePin.connected) { // draw the image only once every 10 samples
+ [self drawSpectrumImage];
}
+ runcycleCount++;
+ OSSpinLockUnlock(&lock);
}
// override outputPins to return them properly sorted
diff --git a/entities/JMXDrawEntity.h b/entities/JMXDrawEntity.h
index 21290d8..df8fbf5 100644
--- a/entities/JMXDrawEntity.h
+++ b/entities/JMXDrawEntity.h
@@ -12,11 +12,7 @@
@class JMXCanvasElement;
-@interface JMXDrawEntity : JMXVideoEntity {
-@private
- JMXCanvasElement *canvas;
- JMXDrawPath *drawPath; // weak reference
-}
+@interface JMXDrawEntity : JMXVideoEntity
@property (readonly) JMXDrawPath *drawPath;
@property (readonly) JMXCanvasElement *canvas;
diff --git a/entities/JMXDrawEntity.mm b/entities/JMXDrawEntity.mm
index 4c153c5..fe59042 100644
--- a/entities/JMXDrawEntity.mm
+++ b/entities/JMXDrawEntity.mm
@@ -15,6 +15,14 @@
JMXV8_EXPORT_NODE_CLASS(JMXDrawEntity);
+@interface JMXDrawEntity ()
+{
+ JMXCanvasElement *canvas;
+ JMXDrawPath *drawPath; // weak reference
+ OSSpinLock lock;
+}
+@end
+
@implementation JMXDrawEntity
@synthesize drawPath, canvas;
@@ -52,37 +60,37 @@ JMXV8_EXPORT_NODE_CLASS(JMXDrawEntity);
- (void)drawRect:(JMXPoint *)rectOrigin size:(JMXSize *)rectSize strokeColor:(NSColor *)strokeColor fillColor:(NSColor *)fillColor
{
- @synchronized(drawPath) {
- [drawPath drawRect:rectOrigin size:rectSize strokeColor:strokeColor fillColor:fillColor];
- }
+ OSSpinLockLock(&lock);
+ [drawPath drawRect:rectOrigin size:rectSize strokeColor:strokeColor fillColor:fillColor];
+ OSSpinLockUnlock(&lock);
}
- (void)drawPolygon:(NSArray *)points strokeColor:(NSColor *)strokeColor fillColor:(NSColor *)fillColor
{
- @synchronized(drawPath) {
- [drawPath drawPolygon:points strokeColor:strokeColor fillColor:fillColor];
- }
+ OSSpinLockLock(&lock);
+ [drawPath drawPolygon:points strokeColor:strokeColor fillColor:fillColor];
+ OSSpinLockUnlock(&lock);
}
- (void)drawPixel:(JMXPoint *)point fillColor:(NSColor *)fillColor
{
- @synchronized(drawPath) {
- [drawPath drawPixel:point fillColor:fillColor];
- }
+ OSSpinLockLock(&lock);
+ [drawPath drawPixel:point fillColor:fillColor];
+ OSSpinLockUnlock(&lock);
}
- (void)drawTriangle:(NSArray *)points strokeColor:(NSColor *)strokeColor fillColor:(NSColor *)fillColor
{
- @synchronized(drawPath) {
- [drawPath drawTriangle:points strokeColor:strokeColor fillColor:fillColor];
- }
+ OSSpinLockLock(&lock);
+ [drawPath drawTriangle:points strokeColor:strokeColor fillColor:fillColor];
+ OSSpinLockUnlock(&lock);
}
- (void)drawCircle:(JMXPoint *)center radius:(NSUInteger)radius strokeColor:(NSColor *)strokeColor fillColor:(NSColor *)fillColor
{
- @synchronized(drawPath) {
- [drawPath drawCircle:center radius:radius strokeColor:strokeColor fillColor:fillColor];
- }
+ OSSpinLockLock(&lock);
+ [drawPath drawCircle:center radius:radius strokeColor:strokeColor fillColor:fillColor];
+ OSSpinLockUnlock(&lock);
}
- (void)clear
@@ -93,12 +101,12 @@ JMXV8_EXPORT_NODE_CLASS(JMXDrawEntity);
- (void)tick:(uint64_t)timeStamp
{
- @synchronized(drawPath) {
- //[drawPath render];
- if (currentFrame)
- [currentFrame release];
- currentFrame = [drawPath.currentFrame retain];
- }
+ OSSpinLockLock(&lock);
+ //[drawPath render];
+ if (currentFrame)
+ [currentFrame release];
+ currentFrame = [drawPath.currentFrame retain];
+ OSSpinLockUnlock(&lock);
[super tick:timeStamp];
}
diff --git a/entities/JMXVideoOutput.mm b/entities/JMXVideoOutput.mm
index ab7a081..3ed4997 100644
--- a/entities/JMXVideoOutput.mm
+++ b/entities/JMXVideoOutput.mm
@@ -57,11 +57,12 @@
- (void)drawFrame:(CIImage *)frame
{
- @synchronized(self) {
- if (currentFrame)
- [currentFrame release];
- currentFrame = [frame retain];
- }
+ static OSSpinLock flock;
+ OSSpinLockLock(&flock);
+ if (currentFrame)
+ [currentFrame release];
+ currentFrame = [frame retain];
+ OSSpinLockUnlock(&flock);
}
- (void)dealloc
@@ -74,27 +75,31 @@
- (JMXSize *)size
{
- @synchronized(self) {
- return [[size retain] autorelease];
- }
+ JMXSize *ret;
+ OSSpinLockLock(&lock);
+ ret = [[size retain] autorelease];
+ OSSpinLockUnlock(&lock);
+ return ret;
}
- (void)setSize:(JMXSize *)newSize
{
- @synchronized(self) {
- if ([size isEqualTo:newSize])
- return;
- [size release];
- if (newSize)
- size = [newSize retain];
- else
- size = nil;
- NSXMLNode *widthAttr = [self attributeForName:@"width"];
- NSXMLNode *heightAttr = [self attributeForName:@"height"];
-
- [widthAttr setStringValue:[NSString stringWithFormat:@"%.0f", size.width]];
- [heightAttr setStringValue:[NSString stringWithFormat:@"%.0f", size.height]];
+ OSSpinLockLock(&lock);
+ if ([size isEqualTo:newSize]) {
+ OSSpinLockUnlock(&lock);
+ return;
}
+ [size release];
+ if (newSize)
+ size = [newSize retain];
+ else
+ size = nil;
+ NSXMLNode *widthAttr = [self attributeForName:@"width"];
+ NSXMLNode *heightAttr = [self attributeForName:@"height"];
+
+ [widthAttr setStringValue:[NSString stringWithFormat:@"%.0f", size.width]];
+ [heightAttr setStringValue:[NSString stringWithFormat:@"%.0f", size.height]];
+ OSSpinLockUnlock(&lock);
}
#pragma mark V8
diff --git a/entities/video_filters/JMXCoreImageFilter.mm b/entities/video_filters/JMXCoreImageFilter.mm
index 53f08af..ac47f61 100644
--- a/entities/video_filters/JMXCoreImageFilter.mm
+++ b/entities/video_filters/JMXCoreImageFilter.mm
@@ -31,6 +31,12 @@
JMXV8_EXPORT_NODE_CLASS(JMXCoreImageFilter);
+@interface JMXCoreImageFilter ()
+{
+ OSSpinLock flock;
+}
+@end
+
@implementation JMXCoreImageFilter
+ (NSArray *)availableFilters
@@ -71,41 +77,41 @@ JMXV8_EXPORT_NODE_CLASS(JMXCoreImageFilter);
- (void)newFrame:(CIImage *)frame
{
- @synchronized(self) {
- if (currentFrame)
- [currentFrame release];
- if (ciFilter) {
- [ciFilter setValue:frame forKey:@"inputImage"];
- currentFrame = [[ciFilter valueForKey:@"outputImage"] retain];
- } else {
- currentFrame = [frame retain];
- }
- [outFrame deliverData:currentFrame];
+ OSSpinLockLock(&flock);
+ if (currentFrame)
+ [currentFrame release];
+ if (ciFilter) {
+ [ciFilter setValue:frame forKey:@"inputImage"];
+ currentFrame = [[ciFilter valueForKey:@"outputImage"] retain];
+ } else {
+ currentFrame = [frame retain];
}
+ [outFrame deliverData:currentFrame];
+ OSSpinLockUnlock(&flock);
}
- (void)setFilterValue:(id)value userData:(id)userData
{
NSString *pinName = (NSString *)userData;
- @synchronized(self) {
- if (ciFilter) {
- @try {
- if ([value isKindOfClass:[JMXPoint class]]) { // XXX
- [ciFilter setValue:[CIVector vectorWithX:[value x] Y:[value y]] forKey:pinName];
- } else if ([value isKindOfClass:[NSColor class]]) {
- CIColor *color = [CIColor colorWithRed:[value redComponent]
- green:[value greenComponent]
- blue:[value blueComponent]];
- [ciFilter setValue:color forKey:pinName];
- } else {
- [ciFilter setValue:value forKey:pinName];
- }
- }
- @catch (NSException * e) {
- // key doesn't exist
+ OSSpinLockLock(&flock);
+ if (ciFilter) {
+ @try {
+ if ([value isKindOfClass:[JMXPoint class]]) { // XXX
+ [ciFilter setValue:[CIVector vectorWithX:[value x] Y:[value y]] forKey:pinName];
+ } else if ([value isKindOfClass:[NSColor class]]) {
+ CIColor *color = [CIColor colorWithRed:[value redComponent]
+ green:[value greenComponent]
+ blue:[value blueComponent]];
+ [ciFilter setValue:color forKey:pinName];
+ } else {
+ [ciFilter setValue:value forKey:pinName];
}
}
+ @catch (NSException * e) {
+ // key doesn't exist
+ }
}
+ OSSpinLockUnlock(&flock);
}
- (void)removeFilterAttributesPins
@@ -145,7 +151,7 @@ JMXV8_EXPORT_NODE_CLASS(JMXCoreImageFilter);
//NSLog(@"Filter Attributes : %@", [newFilter attributes]);
NSArray *inputKeys = [newFilter inputKeys];
NSDictionary *attributes = [newFilter attributes];
- @synchronized(self) {
+ OSSpinLockLock(&flock);
[self removeFilterAttributesPins];
for (NSString *key in inputKeys) {
// TODO - max/min values and display name
@@ -173,7 +179,7 @@ JMXV8_EXPORT_NODE_CLASS(JMXCoreImageFilter);
if (ciFilter)
[ciFilter release];
ciFilter = [newFilter retain];
- }
+ OSSpinLockUnlock(&flock);
if (filter)
[filter release];
filter = [filterName copy];
diff --git a/entities/video_outputs/JMXOpenGLScreen.mm b/entities/video_outputs/JMXOpenGLScreen.mm
index a23f2f6..10d37d4 100644
--- a/entities/video_outputs/JMXOpenGLScreen.mm
+++ b/entities/video_outputs/JMXOpenGLScreen.mm
@@ -441,31 +441,29 @@ static CVReturn renderCallback(CVDisplayLinkRef displayLink,
- (NSColor *)backgroundColor
{
- @synchronized(self) {
- return [[backgroundColor retain] autorelease];
- }
+ OSSpinLockLock(&lock);
+ return [[backgroundColor retain] autorelease];
+ OSSpinLockUnlock(&lock);
}
- (void)setBackgroundColor:(NSColor *)newBackgroundColor
{
- @synchronized(self) {
- if (backgroundColor != newBackgroundColor) {
- [backgroundColor release];
- backgroundColor = [newBackgroundColor retain];
- view.backgroundColor = backgroundColor;
- [view reshape];
- }
+ OSSpinLockLock(&lock);
+ if (backgroundColor != newBackgroundColor) {
+ [backgroundColor release];
+ backgroundColor = [newBackgroundColor retain];
+ view.backgroundColor = backgroundColor;
+ [view reshape];
}
+ OSSpinLockUnlock(&lock);
}
- (void)setSize:(JMXSize *)newSize
{
- //@synchronized(self) {
if (![newSize isEqual:size]) {
[super setSize:newSize];
[controller setSize:newSize];
}
- //}
}
- (void)drawFrame:(CIImage *)frame
@@ -492,22 +490,25 @@ static CVReturn renderCallback(CVDisplayLinkRef displayLink,
- (BOOL)fullScreen
{
- @synchronized(self) {
- return fullScreen;
- }
+ BOOL ret;
+ OSSpinLockLock(&lock);
+ ret = fullScreen;
+ OSSpinLockUnlock(&lock);
+ return ret;
}
- (void)setFullScreen:(BOOL)yesOrNo
{
- @synchronized(self) {
- if (fullScreen == yesOrNo)
- return;
- fullScreen = yesOrNo;
- [view performSelectorOnMainThread:@selector(toggleFullScreen:)
- withObject:self
- waitUntilDone:YES];
+ OSSpinLockLock(&lock);
+ if (fullScreen == yesOrNo) {
+ OSSpinLockUnlock(&lock);
+ return;
}
-
+ fullScreen = yesOrNo;
+ [view performSelectorOnMainThread:@selector(toggleFullScreen:)
+ withObject:self
+ waitUntilDone:YES];
+ OSSpinLockUnlock(&lock);
}
- (BOOL)invertYCoordinates
diff --git a/gui/JMXCodePanel.m b/gui/JMXCodePanel.m
index 7e4a684..bbe5248 100644
--- a/gui/JMXCodePanel.m
+++ b/gui/JMXCodePanel.m
@@ -10,6 +10,12 @@
#import "JMXInputPin.h"
#import "JMXEntity.h"
+@interface JMXCodePanel ()
+{
+ OSSpinLock lock;
+}
+@end
+
@implementation JMXCodePanel
- (id)initWithContentRect:(NSRect)contentRect
@@ -62,39 +68,43 @@
- (void)unsetPin:(NSNotification *)notification
{
- @synchronized(textBuffer) {
- [textBuffer setString:@""];
- }
+ OSSpinLockLock(&lock);
+ [textBuffer setString:@""];
+ OSSpinLockUnlock(&lock);
self.pin = nil;
[self setIsVisible:NO];
}
- (void)setPin:(JMXInputPin *)aPin
{
- @synchronized(self) {
- [super setPin:aPin];
- if (aPin && aPin.type == kJMXCodePin) {
- // if this is a code pin, let's retrieve the actual code being executed
- id owner = aPin.owner;
- if (![owner isKindOfClass:[JMXEntity class]])
- return;
- JMXEntity *entity = (JMXEntity *)owner;
- JMXPin *outputCodePin = nil;
- for (JMXOutputPin *outputPin in [entity outputPins]) {
- if (outputPin.type == kJMXCodePin) {
- outputCodePin = outputPin;
- break;
- }
+ OSSpinLockLock(&lock);
+ [super setPin:aPin];
+ if (aPin && aPin.type == kJMXCodePin) {
+ // if this is a code pin, let's retrieve the actual code being executed
+ id owner = aPin.owner;
+ if (![owner isKindOfClass:[JMXEntity class]]) {
+ OSSpinLockUnlock(&lock);
+ return;
+ }
+ JMXEntity *entity = (JMXEntity *)owner;
+ JMXPin *outputCodePin = nil;
+ for (JMXOutputPin *outputPin in [entity outputPins]) {
+ if (outputPin.type == kJMXCodePin) {
+ outputCodePin = outputPin;
+ break;
}
- if (!outputCodePin)
- return;
- //NSString *text = [[textView textStorage] string];
- [textView setString:@""];
- NSString *data = outputCodePin.data;
- if (data)
- [textView insertText:(NSString *)outputCodePin.data];
}
+ if (!outputCodePin) {
+ OSSpinLockUnlock(&lock);
+ return;
+ }
+ //NSString *text = [[textView textStorage] string];
+ [textView setString:@""];
+ NSString *data = outputCodePin.data;
+ if (data)
+ [textView insertText:(NSString *)outputCodePin.data];
}
+ OSSpinLockUnlock(&lock);
}
@end