Skip to content

Commit

Permalink
fix(blocks runtime): Implement _Block_isDeallocating()
Browse files Browse the repository at this point in the history
This allows us to check whether a block is currently undergoing deallocation in a portable fashion.
  • Loading branch information
ngrewe committed May 29, 2024
1 parent d15e524 commit 628b291
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 5 deletions.
24 changes: 19 additions & 5 deletions arc.mm
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@
#include <assert.h>
#include <vector>
#include <tsl/robin_map.h>
#ifdef HAVE_BLOCK_USE_RR2
#include <Block_private.h>
#endif
#import "lock.h"
#import "objc/runtime.h"
#ifdef EMBEDDED_BLOCKS_RUNTIME
#import "objc/blocks_private.h"
#import "objc/blocks_runtime.h"
#else
#include <Block.h>
#include <Block_private.h>
#endif
#import "nsobject.h"
#import "class.h"
#import "selector.h"
Expand Down Expand Up @@ -867,9 +870,20 @@ static BOOL setObjectHasWeakRefs(id obj)
*addr = obj;
return obj;
}
// If the object is being deallocated return nil.
if (object_getRetainCount_np(obj) == 0)
Class cls = classForObject(obj);
if (cls == static_cast<void*>(&_NSConcreteMallocBlock) ||
cls == static_cast<void*>(&_NSConcreteAutoBlock) ||
cls == static_cast<void*>(&_NSConcreteFinalizingBlock))
{
// Check whether the block is being deallocated and return nil if so
if (_Block_isDeallocating(obj)) {
*addr = nil;
return nil;
}
}
else if (object_getRetainCount_np(obj) == 0)
{
// If the object is being deallocated return nil.
*addr = nil;
return nil;
}
Expand Down
10 changes: 10 additions & 0 deletions blocks_runtime.m
Original file line number Diff line number Diff line change
Expand Up @@ -291,3 +291,13 @@ OBJC_PUBLIC void _Block_release(const void *src)
}
}
}

#ifdef EMBEDDED_BLOCKS_RUNTIME
OBJC_PUBLIC bool _Block_isDeallocating(const void* arg)
{
struct Block_layout *block = (struct Block_layout*)arg;
int *refCountPtr = &((struct Block_layout*)arg)->reserved;
int refCount = __sync_fetch_and_add(refCountPtr, 0);
return refCount == 0;
}
#endif
9 changes: 9 additions & 0 deletions objc/blocks_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,14 @@
#if defined(__clang__) && !defined(__OBJC_RUNTIME_INTERNAL__)
#pragma clang system_header
#endif
#ifdef __cplusplus
#define BLOCKS_EXPORT extern "C"
#else
#define BLOCKS_EXPORT extern
#endif

#include <stdbool.h>
#include "Availability.h"

/*
* This header file exposes some implementation details of the blocks runtime
Expand Down Expand Up @@ -38,6 +45,8 @@ struct Block_descriptor
const char *encoding;
};

OBJC_PUBLIC BLOCKS_EXPORT bool _Block_isDeallocating(const void *aBlock);

// Helper structure
struct Block_layout
{
Expand Down

0 comments on commit 628b291

Please sign in to comment.