rb-scpt 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/bin/rb-scpt-1.0.1.gem +0 -0
  3. data/extconf.rb +12 -12
  4. data/rb-scpt.gemspec +10 -10
  5. data/sample/AB_export_vcard.rb +16 -16
  6. data/sample/AB_list_people_with_emails.rb +4 -4
  7. data/sample/Add_iCal_event.rb +12 -12
  8. data/sample/Create_daily_iCal_todos.rb +28 -28
  9. data/sample/Export_Address_Book_phone_numbers.rb +52 -52
  10. data/sample/Hello_world.rb +10 -10
  11. data/sample/List_iTunes_playlist_names.rb +3 -3
  12. data/sample/Make_Mail_message.rb +24 -24
  13. data/sample/Open_file_in_TextEdit.rb +5 -5
  14. data/sample/Organize_Mail_messages.rb +46 -46
  15. data/sample/Print_folder_tree.rb +5 -5
  16. data/sample/Select_all_HTML_files.rb +6 -6
  17. data/sample/Set_iChat_status.rb +12 -12
  18. data/sample/Simple_Finder_GUI_Scripting.rb +6 -6
  19. data/sample/Stagger_Finder_windows.rb +9 -9
  20. data/sample/TextEdit_demo.rb +71 -71
  21. data/sample/iTunes_top40_to_html.rb +28 -30
  22. data/src/SendThreadSafe.c +293 -293
  23. data/src/SendThreadSafe.h +108 -108
  24. data/src/lib/_aem/aemreference.rb +997 -998
  25. data/src/lib/_aem/codecs.rb +609 -610
  26. data/src/lib/_aem/connect.rb +197 -197
  27. data/src/lib/_aem/encodingsupport.rb +67 -67
  28. data/src/lib/_aem/findapp.rb +75 -75
  29. data/src/lib/_aem/mactypes.rb +241 -242
  30. data/src/lib/_aem/send.rb +268 -268
  31. data/src/lib/_aem/typewrappers.rb +52 -52
  32. data/src/lib/_appscript/defaultterminology.rb +266 -266
  33. data/src/lib/_appscript/referencerenderer.rb +230 -233
  34. data/src/lib/_appscript/reservedkeywords.rb +106 -106
  35. data/src/lib/_appscript/safeobject.rb +125 -125
  36. data/src/lib/_appscript/terminology.rb +448 -449
  37. data/src/lib/aem.rb +238 -238
  38. data/src/lib/kae.rb +1487 -1487
  39. data/src/lib/osax.rb +647 -647
  40. data/src/lib/rb-scpt.rb +1065 -1065
  41. data/src/rbae.c +595 -595
  42. data/test/test_aemreference.rb +104 -107
  43. data/test/test_appscriptcommands.rb +131 -134
  44. data/test/test_appscriptreference.rb +96 -99
  45. data/test/test_codecs.rb +166 -168
  46. data/test/test_findapp.rb +13 -16
  47. data/test/test_mactypes.rb +70 -72
  48. data/test/test_osax.rb +46 -48
  49. data/test/testall.sh +4 -4
  50. metadata +8 -7
@@ -1,72 +1,72 @@
1
1
  /*
2
- File: AESendThreadSafe.c
3
-
4
- Contains: Code to send Apple events in a thread-safe manner.
5
-
6
- Written by: DTS
7
-
8
- Copyright: Copyright (c) 2007 Apple Inc. All Rights Reserved.
9
-
10
- Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc.
11
- ("Apple") in consideration of your agreement to the following
12
- terms, and your use, installation, modification or
13
- redistribution of this Apple software constitutes acceptance of
14
- these terms. If you do not agree with these terms, please do
15
- not use, install, modify or redistribute this Apple software.
16
-
17
- In consideration of your agreement to abide by the following
18
- terms, and subject to these terms, Apple grants you a personal,
19
- non-exclusive license, under Apple's copyrights in this
20
- original Apple software (the "Apple Software"), to use,
21
- reproduce, modify and redistribute the Apple Software, with or
22
- without modifications, in source and/or binary forms; provided
23
- that if you redistribute the Apple Software in its entirety and
24
- without modifications, you must retain this notice and the
25
- following text and disclaimers in all such redistributions of
26
- the Apple Software. Neither the name, trademarks, service marks
27
- or logos of Apple Inc. may be used to endorse or promote
28
- products derived from the Apple Software without specific prior
29
- written permission from Apple. Except as expressly stated in
30
- this notice, no other rights or licenses, express or implied,
31
- are granted by Apple herein, including but not limited to any
32
- patent rights that may be infringed by your derivative works or
33
- by other works in which the Apple Software may be incorporated.
34
-
35
- The Apple Software is provided by Apple on an "AS IS" basis.
36
- APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
37
- WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT,
38
- MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING
39
- THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
40
- COMBINATION WITH YOUR PRODUCTS.
41
-
42
- IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT,
43
- INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
44
- TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
45
- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY
46
- OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
47
- OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY
48
- OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR
49
- OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF
50
- SUCH DAMAGE.
51
-
52
- Change History (most recent first):
53
-
54
- $Log: AESendThreadSafe.c,v $
55
- Revision 1.3 2007/02/27 10:45:15
56
- In the destructor, add an assert that the thread-local storage has been set to NULL. Also fixed a comment typo.
57
-
58
- Revision 1.2 2007/02/12 11:59:09
59
- Added a type cast for the malloc result.
60
-
61
- Revision 1.1 2007/02/09 10:55:24
62
- First checked in.
2
+ File: AESendThreadSafe.c
3
+
4
+ Contains: Code to send Apple events in a thread-safe manner.
5
+
6
+ Written by: DTS
7
+
8
+ Copyright: Copyright (c) 2007 Apple Inc. All Rights Reserved.
9
+
10
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc.
11
+ ("Apple") in consideration of your agreement to the following
12
+ terms, and your use, installation, modification or
13
+ redistribution of this Apple software constitutes acceptance of
14
+ these terms. If you do not agree with these terms, please do
15
+ not use, install, modify or redistribute this Apple software.
16
+
17
+ In consideration of your agreement to abide by the following
18
+ terms, and subject to these terms, Apple grants you a personal,
19
+ non-exclusive license, under Apple's copyrights in this
20
+ original Apple software (the "Apple Software"), to use,
21
+ reproduce, modify and redistribute the Apple Software, with or
22
+ without modifications, in source and/or binary forms; provided
23
+ that if you redistribute the Apple Software in its entirety and
24
+ without modifications, you must retain this notice and the
25
+ following text and disclaimers in all such redistributions of
26
+ the Apple Software. Neither the name, trademarks, service marks
27
+ or logos of Apple Inc. may be used to endorse or promote
28
+ products derived from the Apple Software without specific prior
29
+ written permission from Apple. Except as expressly stated in
30
+ this notice, no other rights or licenses, express or implied,
31
+ are granted by Apple herein, including but not limited to any
32
+ patent rights that may be infringed by your derivative works or
33
+ by other works in which the Apple Software may be incorporated.
34
+
35
+ The Apple Software is provided by Apple on an "AS IS" basis.
36
+ APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
37
+ WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT,
38
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING
39
+ THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
40
+ COMBINATION WITH YOUR PRODUCTS.
41
+
42
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT,
43
+ INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
44
+ TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
45
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY
46
+ OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
47
+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY
48
+ OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR
49
+ OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF
50
+ SUCH DAMAGE.
51
+
52
+ Change History (most recent first):
53
+
54
+ $Log: AESendThreadSafe.c,v $
55
+ Revision 1.3 2007/02/27 10:45:15
56
+ In the destructor, add an assert that the thread-local storage has been set to NULL. Also fixed a comment typo.
57
+
58
+ Revision 1.2 2007/02/12 11:59:09
59
+ Added a type cast for the malloc result.
60
+
61
+ Revision 1.1 2007/02/09 10:55:24
62
+ First checked in.
63
63
 
64
64
 
65
65
  */
66
66
 
67
67
  /*
68
68
 
69
- 2007/06/24 -- Modified by HAS to make AESendMessageThreadSafeSynchronous API-compatible with AESendMessage; renamed SendMessageThreadSafe.
69
+ 2007/06/24 -- Modified by HAS to make AESendMessageThreadSafeSynchronous API-compatible with AESendMessage; renamed SendMessageThreadSafe.
70
70
 
71
71
  */
72
72
 
@@ -80,53 +80,53 @@ First checked in.
80
80
  /////////////////////////////////////////////////////////////////
81
81
 
82
82
  /*
83
- How It Works
84
- ------------
85
- The basic idea behind this module is that it uses per-thread storage to keep
86
- track of an Apple event reply for any given thread. The first time that the
87
- thread calls AESendMessageThreadSafeSynchronous, the per-thread storage will
88
- not be initialised and the code will grab an Apple event reply port and
89
- assign it to the per-thread storage. Subsequent calls to AESendMessageThreadSafeSynchronous
90
- will continue to use that port. When the thread dies, pthreads will automatically
91
- call the destructor for the per-thread storage, and that will clean up the port.
92
-
93
- Because we can't dispose of the reply port (without triggering the Apple
94
- Event Manager bug that's the reason we wrote this code in the first place),
95
- the destructor doesn't actually dispose of the port. Rather, it adds the
96
- port to a pool of ports that are available for reuse. The next time a thread
97
- needs to allocate a port, it will grab it from the pool rather than allocating
98
- it from scratch.
99
-
100
- This technique means that the code still 'leaks' Apple event reply ports, but
101
- the size of the leak is limited to the maximum number of threads that you run
102
- simultaneously. This isn't a problem in practice.
83
+ How It Works
84
+ ------------
85
+ The basic idea behind this module is that it uses per-thread storage to keep
86
+ track of an Apple event reply for any given thread. The first time that the
87
+ thread calls AESendMessageThreadSafeSynchronous, the per-thread storage will
88
+ not be initialised and the code will grab an Apple event reply port and
89
+ assign it to the per-thread storage. Subsequent calls to AESendMessageThreadSafeSynchronous
90
+ will continue to use that port. When the thread dies, pthreads will automatically
91
+ call the destructor for the per-thread storage, and that will clean up the port.
92
+
93
+ Because we can't dispose of the reply port (without triggering the Apple
94
+ Event Manager bug that's the reason we wrote this code in the first place),
95
+ the destructor doesn't actually dispose of the port. Rather, it adds the
96
+ port to a pool of ports that are available for reuse. The next time a thread
97
+ needs to allocate a port, it will grab it from the pool rather than allocating
98
+ it from scratch.
99
+
100
+ This technique means that the code still 'leaks' Apple event reply ports, but
101
+ the size of the leak is limited to the maximum number of threads that you run
102
+ simultaneously. This isn't a problem in practice.
103
103
  */
104
104
 
105
105
  /////////////////////////////////////////////////////////////////
106
106
 
107
- // The PerThreadStorage structure is a trivial wrapper around the Mach port.
108
- // I added this because I need to attach this structure a thread using
109
- // per-thread storage. The API for that (<x-man-page://3/pthread_setspecific>)
110
- // is pointer based. I could've just cast the Mach port to a (void *), but
111
- // that's ugly because of a) pointer size issues (are pointers always bigger than
107
+ // The PerThreadStorage structure is a trivial wrapper around the Mach port.
108
+ // I added this because I need to attach this structure a thread using
109
+ // per-thread storage. The API for that (<x-man-page://3/pthread_setspecific>)
110
+ // is pointer based. I could've just cast the Mach port to a (void *), but
111
+ // that's ugly because of a) pointer size issues (are pointers always bigger than
112
112
  // ints?), and b) because it implies an equivalent between NULL and MACH_PORT_NULL.
113
113
  // Given this, I simply decided to create a structure to wrap the Mach port.
114
114
 
115
115
  enum {
116
- kPerThreadStorageMagic = 'PTSm'
116
+ kPerThreadStorageMagic = 'PTSm'
117
117
  };
118
118
 
119
119
  struct PerThreadStorage {
120
- OSType magic; // must be kPerThreadStorageMagic
121
- mach_port_t port;
120
+ OSType magic; // must be kPerThreadStorageMagic
121
+ mach_port_t port;
122
122
  };
123
123
  typedef struct PerThreadStorage PerThreadStorage;
124
124
 
125
- // The following static variables manage the per-thread storage key
126
- // (sPerThreadStorageKey) and the pool of Mach ports (wrapped in
125
+ // The following static variables manage the per-thread storage key
126
+ // (sPerThreadStorageKey) and the pool of Mach ports (wrapped in
127
127
  // PerThreadStorage structures) that are not currently attached to a thread.
128
128
 
129
- static pthread_once_t sInited = PTHREAD_ONCE_INIT; // covers initialisation of all of the
129
+ static pthread_once_t sInited = PTHREAD_ONCE_INIT; // covers initialisation of all of the
130
130
  // following static variables
131
131
 
132
132
  static OSStatus sPerThreadStorageKeyInitErrNum; // latches result of initialisation
@@ -134,247 +134,247 @@ static OSStatus sPerThreadStorageKeyInitErrNum; // latches result of
134
134
  static pthread_key_t sPerThreadStorageKey = 0; // key for our per-thread storage
135
135
 
136
136
  static pthread_mutex_t sPoolMutex; // protects sPool
137
- static CFMutableArrayRef sPool; // array of (PerThreadStorage *), holds
138
- // the ports that aren't currently bound to
137
+ static CFMutableArrayRef sPool; // array of (PerThreadStorage *), holds
138
+ // the ports that aren't currently bound to
139
139
  // a thread
140
140
 
141
141
  static void PerThreadStorageDestructor(void *keyValue); // forward declaration
142
142
 
143
143
  static void InitRoutine(void)
144
- // Call once (via pthread_once) to initialise various static variables.
144
+ // Call once (via pthread_once) to initialise various static variables.
145
145
  {
146
- OSStatus err;
147
-
148
- // Create the per-thread storage key. Note that we assign a destructor to this key;
149
- // pthreads call the destructor to clean up that item of per-thread storage whenever
150
- // a thread terminates.
151
-
152
- err = (OSStatus) pthread_key_create(&sPerThreadStorageKey, PerThreadStorageDestructor);
153
-
154
- // Create the pool of Mach ports that aren't bound to any thread, and its associated
155
- // lock. The pool starts out empty.
156
-
157
- if (err == noErr) {
158
- err = (OSStatus) pthread_mutex_init(&sPoolMutex, NULL);
159
- }
160
- if (err == noErr) {
161
- sPool = CFArrayCreateMutable(NULL, 0, NULL);
162
- if (sPool == NULL) {
163
- err = coreFoundationUnknownErr;
164
- }
146
+ OSStatus err;
147
+
148
+ // Create the per-thread storage key. Note that we assign a destructor to this key;
149
+ // pthreads call the destructor to clean up that item of per-thread storage whenever
150
+ // a thread terminates.
151
+
152
+ err = (OSStatus) pthread_key_create(&sPerThreadStorageKey, PerThreadStorageDestructor);
153
+
154
+ // Create the pool of Mach ports that aren't bound to any thread, and its associated
155
+ // lock. The pool starts out empty.
156
+
157
+ if (err == noErr) {
158
+ err = (OSStatus) pthread_mutex_init(&sPoolMutex, NULL);
159
+ }
160
+ if (err == noErr) {
161
+ sPool = CFArrayCreateMutable(NULL, 0, NULL);
162
+ if (sPool == NULL) {
163
+ err = coreFoundationUnknownErr;
165
164
  }
166
- assert(err == 0);
167
-
168
- sPerThreadStorageKeyInitErrNum = err;
165
+ }
166
+ assert(err == 0);
167
+
168
+ sPerThreadStorageKeyInitErrNum = err;
169
169
  }
170
170
 
171
171
  static OSStatus AllocatePortFromPool(PerThreadStorage **storagePtr)
172
- // Grab a Mach port from sPool; if sPool is empty, create one.
172
+ // Grab a Mach port from sPool; if sPool is empty, create one.
173
173
  {
174
- OSStatus err;
175
- OSStatus junk;
176
- PerThreadStorage * storage;
177
-
178
- assert( storagePtr != NULL);
179
- assert(*storagePtr == NULL);
180
-
181
- storage = NULL;
182
-
183
- // First try to get an entry from pool. We try to grab the last one because
184
- // that minimises the amount of copying that CFArrayRemoveValueAtIndex has to
185
- // do.
186
-
187
- err = (OSStatus) pthread_mutex_lock(&sPoolMutex);
188
- if (err == noErr) {
189
- CFIndex poolCount;
190
-
191
- poolCount = CFArrayGetCount(sPool);
192
- if (poolCount > 0) {
193
- storage = (PerThreadStorage *) CFArrayGetValueAtIndex(sPool, poolCount - 1);
194
- CFArrayRemoveValueAtIndex(sPool, poolCount - 1);
195
- }
196
-
197
- junk = (OSStatus) pthread_mutex_unlock(&sPoolMutex);
198
- assert(junk == noErr);
199
- }
174
+ OSStatus err;
175
+ OSStatus junk;
176
+ PerThreadStorage * storage;
200
177
 
201
- // If we failed to find an entry in the pool, create a new one.
202
-
203
- if ( (err == noErr) && (storage == NULL) ) {
204
- storage = (PerThreadStorage *) malloc(sizeof(*storage));
205
- if (storage == NULL) {
206
- err = memFullErr;
207
- } else {
208
- storage->magic = kPerThreadStorageMagic;
209
- storage->port = MACH_PORT_NULL;
210
-
211
- err = (OSStatus) mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &storage->port);
212
- if (err != noErr) {
213
- assert(storage->port == MACH_PORT_NULL);
214
- free(storage);
215
- storage = NULL;
216
- }
217
- }
178
+ assert( storagePtr != NULL);
179
+ assert(*storagePtr == NULL);
180
+
181
+ storage = NULL;
182
+
183
+ // First try to get an entry from pool. We try to grab the last one because
184
+ // that minimises the amount of copying that CFArrayRemoveValueAtIndex has to
185
+ // do.
186
+
187
+ err = (OSStatus) pthread_mutex_lock(&sPoolMutex);
188
+ if (err == noErr) {
189
+ CFIndex poolCount;
190
+
191
+ poolCount = CFArrayGetCount(sPool);
192
+ if (poolCount > 0) {
193
+ storage = (PerThreadStorage *) CFArrayGetValueAtIndex(sPool, poolCount - 1);
194
+ CFArrayRemoveValueAtIndex(sPool, poolCount - 1);
218
195
  }
219
- if (err == noErr) {
220
- *storagePtr = storage;
196
+
197
+ junk = (OSStatus) pthread_mutex_unlock(&sPoolMutex);
198
+ assert(junk == noErr);
199
+ }
200
+
201
+ // If we failed to find an entry in the pool, create a new one.
202
+
203
+ if ( (err == noErr) && (storage == NULL) ) {
204
+ storage = (PerThreadStorage *) malloc(sizeof(*storage));
205
+ if (storage == NULL) {
206
+ err = memFullErr;
207
+ } else {
208
+ storage->magic = kPerThreadStorageMagic;
209
+ storage->port = MACH_PORT_NULL;
210
+
211
+ err = (OSStatus) mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &storage->port);
212
+ if (err != noErr) {
213
+ assert(storage->port == MACH_PORT_NULL);
214
+ free(storage);
215
+ storage = NULL;
216
+ }
221
217
  }
222
-
223
- assert( (err == noErr) == (*storagePtr != NULL) );
224
- assert( (*storagePtr == NULL) || ((*storagePtr)->magic == kPerThreadStorageMagic) );
225
- assert( (*storagePtr == NULL) || ((*storagePtr)->port != MACH_PORT_NULL) );
226
-
227
- return err;
218
+ }
219
+ if (err == noErr) {
220
+ *storagePtr = storage;
221
+ }
222
+
223
+ assert( (err == noErr) == (*storagePtr != NULL) );
224
+ assert( (*storagePtr == NULL) || ((*storagePtr)->magic == kPerThreadStorageMagic) );
225
+ assert( (*storagePtr == NULL) || ((*storagePtr)->port != MACH_PORT_NULL) );
226
+
227
+ return err;
228
228
  }
229
229
 
230
230
  static void ReturnPortToPool(PerThreadStorage * storage)
231
- // Returns a port to sPool.
231
+ // Returns a port to sPool.
232
232
  {
233
- OSStatus err;
233
+ OSStatus err;
234
234
 
235
- assert(storage != NULL);
236
- assert(storage->magic == kPerThreadStorageMagic);
237
- assert(storage->port != MACH_PORT_NULL);
235
+ assert(storage != NULL);
236
+ assert(storage->magic == kPerThreadStorageMagic);
237
+ assert(storage->port != MACH_PORT_NULL);
238
238
 
239
- err = (OSStatus) pthread_mutex_lock(&sPoolMutex);
240
- if (err == noErr) {
241
- CFArrayAppendValue(sPool, storage);
242
-
243
- err = (OSStatus) pthread_mutex_unlock(&sPoolMutex);
244
- }
245
- assert(err == noErr);
239
+ err = (OSStatus) pthread_mutex_lock(&sPoolMutex);
240
+ if (err == noErr) {
241
+ CFArrayAppendValue(sPool, storage);
242
+
243
+ err = (OSStatus) pthread_mutex_unlock(&sPoolMutex);
244
+ }
245
+ assert(err == noErr);
246
246
  }
247
247
 
248
248
  // Main Thread Notes
249
249
  // -----------------
250
- // There are two reasons why we don't assign a reply port to the main thread.
251
- // First, the main thread already has a reply port created for it by Apple
252
- // Event Manager. Thus, we don't need a specific reply port. Also, the
253
- // destructor for per-thread storage isn't called for the main thread, so
254
- // we wouldn't get a chance to clean up (although that's not really a problem
250
+ // There are two reasons why we don't assign a reply port to the main thread.
251
+ // First, the main thread already has a reply port created for it by Apple
252
+ // Event Manager. Thus, we don't need a specific reply port. Also, the
253
+ // destructor for per-thread storage isn't called for the main thread, so
254
+ // we wouldn't get a chance to clean up (although that's not really a problem
255
255
  // in practice).
256
256
 
257
257
  static OSStatus BindReplyMachPortToThread(mach_port_t *replyPortPtr)
258
- // Get a reply port for this thread, remembering that we've done this
259
- // in per-thread storage.
260
- //
261
- // On success, *replyPortPtr is the port to use for this thread's reply
262
- // port. It will be MACH_PORT_NULL if you call it from the main thread.
258
+ // Get a reply port for this thread, remembering that we've done this
259
+ // in per-thread storage.
260
+ //
261
+ // On success, *replyPortPtr is the port to use for this thread's reply
262
+ // port. It will be MACH_PORT_NULL if you call it from the main thread.
263
263
  {
264
- OSStatus err;
265
-
266
- assert( replyPortPtr != NULL);
267
- assert(*replyPortPtr == MACH_PORT_NULL);
268
-
269
- // Initialise ourselves the first time that we're called.
270
-
271
- err = (OSStatus) pthread_once(&sInited, InitRoutine);
272
-
273
- // If something went wrong, return the latched error.
274
-
275
- if ( (err == noErr) && (sPerThreadStorageKeyInitErrNum != noErr) ) {
276
- err = sPerThreadStorageKeyInitErrNum;
277
- }
278
-
279
- // Now do the real work.
280
-
281
- if (err == noErr) {
282
- if ( pthread_main_np() ) {
283
- // This is the main thread, so do nothing; leave *replyPortPtr set
284
- // to MACH_PORT_NULL.
285
- assert(*replyPortPtr == MACH_PORT_NULL);
286
- } else {
287
- PerThreadStorage * storage;
288
-
289
- // Get the per-thread storage for this thread.
290
-
291
- storage = (PerThreadStorage *) pthread_getspecific(sPerThreadStorageKey);
292
- if (storage == NULL) {
293
-
294
- // The per-thread storage hasn't been allocated yet for this specific
295
- // thread. Let's go allocate it and attach it to this thread.
296
-
297
- err = AllocatePortFromPool(&storage);
298
- if (err == noErr) {
299
- err = (OSStatus) pthread_setspecific(sPerThreadStorageKey, (void *) storage);
300
- if (err != noErr) {
301
- ReturnPortToPool(storage);
302
- storage = NULL;
303
- }
304
- }
305
- }
306
- assert( (err == noErr) == (storage != NULL) );
307
-
308
- // If all went well, copy the port out to our client.
309
-
310
- if (err == noErr) {
311
- assert(storage->magic == kPerThreadStorageMagic);
312
- assert(storage->port != MACH_PORT_NULL);
313
- *replyPortPtr = storage->port;
314
- }
264
+ OSStatus err;
265
+
266
+ assert( replyPortPtr != NULL);
267
+ assert(*replyPortPtr == MACH_PORT_NULL);
268
+
269
+ // Initialise ourselves the first time that we're called.
270
+
271
+ err = (OSStatus) pthread_once(&sInited, InitRoutine);
272
+
273
+ // If something went wrong, return the latched error.
274
+
275
+ if ( (err == noErr) && (sPerThreadStorageKeyInitErrNum != noErr) ) {
276
+ err = sPerThreadStorageKeyInitErrNum;
277
+ }
278
+
279
+ // Now do the real work.
280
+
281
+ if (err == noErr) {
282
+ if ( pthread_main_np() ) {
283
+ // This is the main thread, so do nothing; leave *replyPortPtr set
284
+ // to MACH_PORT_NULL.
285
+ assert(*replyPortPtr == MACH_PORT_NULL);
286
+ } else {
287
+ PerThreadStorage * storage;
288
+
289
+ // Get the per-thread storage for this thread.
290
+
291
+ storage = (PerThreadStorage *) pthread_getspecific(sPerThreadStorageKey);
292
+ if (storage == NULL) {
293
+
294
+ // The per-thread storage hasn't been allocated yet for this specific
295
+ // thread. Let's go allocate it and attach it to this thread.
296
+
297
+ err = AllocatePortFromPool(&storage);
298
+ if (err == noErr) {
299
+ err = (OSStatus) pthread_setspecific(sPerThreadStorageKey, (void *) storage);
300
+ if (err != noErr) {
301
+ ReturnPortToPool(storage);
302
+ storage = NULL;
303
+ }
315
304
  }
305
+ }
306
+ assert( (err == noErr) == (storage != NULL) );
307
+
308
+ // If all went well, copy the port out to our client.
309
+
310
+ if (err == noErr) {
311
+ assert(storage->magic == kPerThreadStorageMagic);
312
+ assert(storage->port != MACH_PORT_NULL);
313
+ *replyPortPtr = storage->port;
314
+ }
316
315
  }
316
+ }
317
317
 
318
- // no error + MACH_PORT_NULL is a valid response if we're on the main
319
- // thread.
320
- //
321
- // assert( (err == noErr) == (*replyPortPtr != MACH_PORT_NULL) );
322
- assert( (*replyPortPtr == MACH_PORT_NULL) || (err == noErr) );
323
-
324
- return err;
318
+ // no error + MACH_PORT_NULL is a valid response if we're on the main
319
+ // thread.
320
+ //
321
+ // assert( (err == noErr) == (*replyPortPtr != MACH_PORT_NULL) );
322
+ assert( (*replyPortPtr == MACH_PORT_NULL) || (err == noErr) );
323
+
324
+ return err;
325
325
  }
326
326
 
327
327
  static void PerThreadStorageDestructor(void *keyValue)
328
- // Called by pthreads when a thread dies and it has a non-null value for our
329
- // per-thread storage key. We use this callback to return the thread's
330
- // Apple event reply port to the pool.
328
+ // Called by pthreads when a thread dies and it has a non-null value for our
329
+ // per-thread storage key. We use this callback to return the thread's
330
+ // Apple event reply port to the pool.
331
331
  {
332
- PerThreadStorage * storage;
332
+ PerThreadStorage * storage;
333
+
334
+ storage = (PerThreadStorage *) keyValue;
335
+ assert(storage != NULL); // pthread won't call us if it's NULL
336
+ assert(storage->magic == kPerThreadStorageMagic);
337
+ assert(storage->port != MACH_PORT_NULL);
338
+
339
+ // Return the port associated with this thread to the pool.
333
340
 
334
- storage = (PerThreadStorage *) keyValue;
335
- assert(storage != NULL); // pthread won't call us if it's NULL
336
- assert(storage->magic == kPerThreadStorageMagic);
337
- assert(storage->port != MACH_PORT_NULL);
338
-
339
- // Return the port associated with this thread to the pool.
340
-
341
- ReturnPortToPool(storage);
341
+ ReturnPortToPool(storage);
342
342
 
343
- // pthreads has already set this thread's per-thread storage for our key to
344
- // NULL before calling us. So we don't need to do anything to remove it.
343
+ // pthreads has already set this thread's per-thread storage for our key to
344
+ // NULL before calling us. So we don't need to do anything to remove it.
345
345
 
346
- assert( pthread_getspecific(sPerThreadStorageKey) == NULL );
346
+ assert( pthread_getspecific(sPerThreadStorageKey) == NULL );
347
347
  }
348
348
 
349
349
  OSStatus SendMessageThreadSafe(
350
- AppleEvent * eventPtr,
351
- AppleEvent * replyPtr,
352
- AESendMode sendMode,
353
- long timeOutInTicks
354
- )
355
- // See comment in header.
350
+ AppleEvent * eventPtr,
351
+ AppleEvent * replyPtr,
352
+ AESendMode sendMode,
353
+ long timeOutInTicks
354
+ )
355
+ // See comment in header.
356
356
  {
357
- OSStatus err = noErr;
358
- mach_port_t replyPort;
359
- assert(eventPtr != NULL);
360
- assert(replyPtr != NULL);
361
-
362
- if (sendMode && kAEWaitReply) {
363
- replyPort = MACH_PORT_NULL;
364
-
365
- // Set up the reply port if necessary.
366
-
367
- err = BindReplyMachPortToThread(&replyPort);
368
- if ( (err == noErr) && (replyPort != MACH_PORT_NULL) ) {
369
- err = AEPutAttributePtr(eventPtr, keyReplyPortAttr, typeMachPort, &replyPort, sizeof(replyPort));
370
- }
371
- }
372
-
373
- // Call through to AESendMessage.
374
-
375
- if (err == noErr) {
376
- err = AESendMessage(eventPtr, replyPtr, sendMode, timeOutInTicks);
357
+ OSStatus err = noErr;
358
+ mach_port_t replyPort;
359
+ assert(eventPtr != NULL);
360
+ assert(replyPtr != NULL);
361
+
362
+ if (sendMode && kAEWaitReply) {
363
+ replyPort = MACH_PORT_NULL;
364
+
365
+ // Set up the reply port if necessary.
366
+
367
+ err = BindReplyMachPortToThread(&replyPort);
368
+ if ( (err == noErr) && (replyPort != MACH_PORT_NULL) ) {
369
+ err = AEPutAttributePtr(eventPtr, keyReplyPortAttr, typeMachPort, &replyPort, sizeof(replyPort));
377
370
  }
378
-
379
- return err;
371
+ }
372
+
373
+ // Call through to AESendMessage.
374
+
375
+ if (err == noErr) {
376
+ err = AESendMessage(eventPtr, replyPtr, sendMode, timeOutInTicks);
377
+ }
378
+
379
+ return err;
380
380
  }