@@ -29,6 +29,8 @@ export NSObject, retain, release, autorelease, is_kind_of
29
29
@autoproperty hash:: NSUInteger
30
30
@autoproperty description:: id{NSString}
31
31
@autoproperty debugDescription:: id{NSString}
32
+
33
+ @autoproperty retainCount:: NSUInteger
32
34
end
33
35
34
36
function Base. show (io:: IO , :: MIME"text/plain" , obj:: NSObject )
@@ -409,6 +411,16 @@ export NSAutoreleasePool, @autoreleasepool, drain
409
411
410
412
@objcwrapper NSAutoreleasePool <: NSObject
411
413
414
+ """
415
+ NSAutoreleasePool()
416
+
417
+ Create a new autorelease pool. This is a low-level wrapper around the Objective-C
418
+ `NSAutoreleasePool` class, and should be used with care. For example, it does not
419
+ automatically get released, or drain the pool on finalization.
420
+
421
+ For high-level usage, consider using the do-block syntax, or [`@autoreleasepool`](@ref)
422
+ instead.
423
+ """
412
424
function NSAutoreleasePool ()
413
425
obj = NSAutoreleasePool (@objc [NSAutoreleasePool alloc]:: id{NSAutoreleasePool} )
414
426
# XXX : this init call itself requires an autoreleasepool to be active...
421
433
drain (pool:: NSAutoreleasePool ) = @objc [pool:: id{NSAutoreleasePool} drain]:: Cvoid
422
434
423
435
# high-level interface to wrap Julia code in an autorelease pool
424
- const NSAutoreleaseLock = ReentrantLock ()
436
+
437
+ """
438
+ NSAutoreleasePool() do
439
+ # ...
440
+ end
441
+
442
+ High-level interface to wrap Julia code in an autorelease pool. This is equivalent to
443
+ `@autoreleasepool` in Objective-C, and ensures that the pool is drained after the
444
+ enclosed code block has finished.
445
+
446
+ Note that due to technical limitations, this API prevents the current task from migrating
447
+ to another thread. In addition, only one autorelease do-block can be active at a time.
448
+ To disable these limitations, use the unsafe [`NSUnsafeAutoreleasePool`](@ref) instead.
449
+
450
+ See also: [`@autoreleasepool`](@ref)
451
+ """
425
452
function NSAutoreleasePool (f:: Base.Callable )
426
453
# we cannot switch between multiple autorelease pools, so ensure only one is ever active.
427
454
# XXX : support multiple pools, as long as they run on separate threads?
@@ -442,12 +469,68 @@ function NSAutoreleasePool(f::Base.Callable)
442
469
end
443
470
end
444
471
end
472
+ const NSAutoreleaseLock = ReentrantLock ()
473
+
474
+ function NSUnsafeAutoreleasePool (f:: Base.Callable )
475
+ pool = NSAutoreleasePool ()
476
+ try
477
+ f ()
478
+ finally
479
+ drain (pool)
480
+ end
481
+ end
482
+
445
483
446
- # for compatibility with Objective-C code
447
- macro autoreleasepool (ex)
448
- quote
449
- $ NSAutoreleasePool () do
450
- $ (esc (ex))
484
+ """
485
+ @autoreleasepool [kwargs...] code...
486
+ @autoreleasepool [kwargs...] function ... end
487
+
488
+ High-level interface to wrap Julia code in an autorelease pool. This macro can be used
489
+ within a function, or as a function decorator. In both cases, the macro ensures that the
490
+ contained code is wrapped in an autorelease pool, and that the pool is drained after the
491
+ enclosed code block has finished.
492
+
493
+ See also: [`NSAutoreleasePool`](@ref)
494
+ """
495
+ macro autoreleasepool (ex... )
496
+ code = ex[end ]
497
+ kwargs = ex[1 : end - 1 ]
498
+
499
+ # extract keyword arguments that are handled by this macro
500
+ unsafe = false
501
+ for kwarg in kwargs
502
+ if Meta. isexpr (kwarg, :(= ))
503
+ key, value = kwarg. args
504
+ if key == :unsafe
505
+ isa (value, Bool) || throw (ArgumentError (" Invalid value for keyword argument `unsafe`: got `$value `, expected literal boolean value" ))
506
+ unsafe = value
507
+ else
508
+ error (" Invalid keyword argument to @autoreleasepool: $kwarg " )
509
+ end
510
+ else
511
+ throw (ArgumentError (" Invalid keyword argument to @autoreleasepool: $kwarg " ))
512
+ end
513
+ end
514
+ f = unsafe ? NSUnsafeAutoreleasePool : NSAutoreleasePool
515
+
516
+ if Meta. isexpr (code, :function )
517
+ # function definition
518
+ sig = code. args[1 ]
519
+ @assert Meta. isexpr (sig, :call )
520
+ body = code. args[2 ]
521
+ @assert Meta. isexpr (body, :block )
522
+ managed_body = quote
523
+ $ f () do
524
+ $ body
525
+ end
526
+ end
527
+ esc (Expr (:function , sig, managed_body))
528
+ else
529
+ # code block
530
+ quote
531
+ $ f () do
532
+ $ (esc (code))
533
+ end
451
534
end
452
535
end
453
536
end
0 commit comments