Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Store ASLayoutElementContext in Thread-Local Storage #trivial #268

Merged
merged 1 commit into from
May 14, 2017
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 19 additions & 20 deletions Source/Layout/ASLayoutElement.mm
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
#import <AsyncDisplayKit/ASThread.h>
#import <AsyncDisplayKit/ASObjectDescriptionHelpers.h>

#import <map>
#import <atomic>

#if YOGA
Expand Down Expand Up @@ -62,39 +61,39 @@ ASLayoutElementContext ASLayoutElementContextMake(int32_t transitionID)
return _ASLayoutElementContextMake(transitionID);
}

// Note: This is a non-recursive static lock. If it needs to be recursive, use ASDISPLAYNODE_MUTEX_RECURSIVE_INITIALIZER
static ASDN::StaticMutex _layoutElementContextLock = ASDISPLAYNODE_MUTEX_INITIALIZER;
static std::map<mach_port_t, ASLayoutElementContext> layoutElementContextMap;
pthread_key_t ASLayoutElementContextKey;

static inline mach_port_t ASLayoutElementGetCurrentContextKey()
// pthread_key_create must be called before the key can be used. This function does that.
void ASLayoutElementContextEnsureKey()
{
return pthread_mach_thread_np(pthread_self());
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
pthread_key_create(&ASLayoutElementContextKey, free);
});
}

void ASLayoutElementSetCurrentContext(struct ASLayoutElementContext context)
{
const mach_port_t key = ASLayoutElementGetCurrentContextKey();
ASDN::StaticMutexLocker l(_layoutElementContextLock);
layoutElementContextMap[key] = context;
ASLayoutElementContextEnsureKey();
ASDisplayNodeCAssert(pthread_getspecific(ASLayoutElementContextKey) == NULL, @"Nested ASLayoutElementContexts aren't supported.");
pthread_setspecific(ASLayoutElementContextKey, new ASLayoutElementContext(context));
}

struct ASLayoutElementContext ASLayoutElementGetCurrentContext()
{
const mach_port_t key = ASLayoutElementGetCurrentContextKey();
ASDN::StaticMutexLocker l(_layoutElementContextLock);
const auto it = layoutElementContextMap.find(key);
if (it != layoutElementContextMap.end()) {
// Found an interator with above key. "it->first" is the key itself, "it->second" is the context value.
return it->second;
}
return ASLayoutElementContextNull;
ASLayoutElementContextEnsureKey();
auto heapCtx = (ASLayoutElementContext *)pthread_getspecific(ASLayoutElementContextKey);
return (heapCtx ? *heapCtx : ASLayoutElementContextNull);
}

void ASLayoutElementClearCurrentContext()
{
const mach_port_t key = ASLayoutElementGetCurrentContextKey();
ASDN::StaticMutexLocker l(_layoutElementContextLock);
layoutElementContextMap.erase(key);
ASLayoutElementContextEnsureKey();
auto heapCtx = (ASLayoutElementContext *)pthread_getspecific(ASLayoutElementContextKey);
if (heapCtx != NULL) {
delete heapCtx;
}
pthread_setspecific(ASLayoutElementContextKey, NULL);
}

#pragma mark - ASLayoutElementStyle
Expand Down