@@ -1390,8 +1390,22 @@ CF_PRIVATE int asprintf(char **ret, const char *format, ...) {
13901390extern void swift_retain (void * );
13911391extern void swift_release (void * );
13921392
1393+ #if TARGET_OS_WIN32
1394+ typedef struct _CFThreadSpecificData {
1395+ CFTypeRef value ;
1396+ _CFThreadSpecificKey key ;
1397+ } _CFThreadSpecificData ;
1398+ #endif
1399+
13931400static void _CFThreadSpecificDestructor (void * ctx ) {
1401+ #if TARGET_OS_WIN32
1402+ _CFThreadSpecificData * data = (_CFThreadSpecificData * )ctx ;
1403+ FlsSetValue (data -> key , NULL );
1404+ swift_release (data -> value );
1405+ free (data );
1406+ #else
13941407 swift_release (ctx );
1408+ #endif
13951409}
13961410
13971411_CFThreadSpecificKey _CFThreadSpecificKeyCreate () {
@@ -1406,18 +1420,36 @@ _CFThreadSpecificKey _CFThreadSpecificKeyCreate() {
14061420
14071421CFTypeRef _Nullable _CFThreadSpecificGet (_CFThreadSpecificKey key ) {
14081422#if TARGET_OS_WIN32
1409- return (CFTypeRef )FlsGetValue (key );
1423+ _CFThreadSpecificData * data = (_CFThreadSpecificData * )FlsGetValue (key );
1424+ if (data == NULL ) {
1425+ return NULL ;
1426+ }
1427+ return data -> value ;
14101428#else
14111429 return (CFTypeRef )pthread_getspecific (key );
14121430#endif
14131431}
14141432
14151433void _CFThreadSpecificSet (_CFThreadSpecificKey key , CFTypeRef _Nullable value ) {
1434+ // Intentionally not calling `swift_release` for previous value.
1435+ // OperationQueue uses these API (through NSThreadSpecific), and balances
1436+ // retain count manually.
14161437#if TARGET_OS_WIN32
1438+ free (FlsGetValue (key ));
1439+
1440+ _CFThreadSpecificData * data = NULL ;
14171441 if (value != NULL ) {
1442+ data = malloc (sizeof (_CFThreadSpecificData ));
1443+ if (!data ) {
1444+ HALT_MSG ("Out of memory" );
1445+ }
1446+ data -> value = value ;
1447+ data -> key = key ;
1448+
14181449 swift_retain ((void * )value );
14191450 }
1420- FlsSetValue (key , value );
1451+
1452+ FlsSetValue (key , data );
14211453#else
14221454 if (value != NULL ) {
14231455 swift_retain ((void * )value );
0 commit comments