Return to thread_value.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / threading / windows |
1.1 misho 1: /* 2: * Copyright (C) 2013 Martin Willi 3: * Copyright (C) 2013 revosec AG 4: * 5: * This program is free software; you can redistribute it and/or modify it 6: * under the terms of the GNU General Public License as published by the 7: * Free Software Foundation; either version 2 of the License, or (at your 8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. 9: * 10: * This program is distributed in the hope that it will be useful, but 11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13: * for more details. 14: */ 15: 16: #include "thread.h" 17: 18: #include <threading/thread_value.h> 19: 20: 21: typedef struct private_thread_value_t private_thread_value_t; 22: 23: /** 24: * Unified thread_value_t implementation 25: */ 26: struct private_thread_value_t { 27: 28: /** 29: * Public interface. 30: */ 31: thread_value_t public; 32: 33: union { 34: 35: /** 36: * Cleanup function 37: */ 38: thread_cleanup_t cleanup; 39: 40: /** 41: * Windows TLS index, if used 42: */ 43: DWORD index; 44: }; 45: }; 46: 47: /** 48: * TLS entry 49: */ 50: typedef struct { 51: /** TLS value */ 52: void *value; 53: /** cleanup handler function */ 54: thread_cleanup_t cleanup; 55: } entry_t; 56: 57: /** 58: * See windows/thread.h 59: */ 60: void thread_tls_cleanup(void *value) 61: { 62: entry_t *entry = (entry_t*)value; 63: 64: if (entry->cleanup) 65: { 66: entry->cleanup(entry->value); 67: } 68: free(entry); 69: } 70: 71: METHOD(thread_value_t, tls_set, void, 72: private_thread_value_t *this, void *val) 73: { 74: entry_t *entry; 75: 76: if (val) 77: { 78: INIT(entry, 79: .cleanup = this->cleanup, 80: .value = val, 81: ); 82: 83: free(thread_tls_put(this, entry)); 84: } 85: else 86: { 87: free(thread_tls_remove(this)); 88: } 89: } 90: 91: METHOD(thread_value_t, tls_get, void*, 92: private_thread_value_t *this) 93: { 94: entry_t *entry; 95: 96: entry = thread_tls_get(this); 97: if (entry) 98: { 99: return entry->value; 100: } 101: return NULL; 102: } 103: 104: METHOD(thread_value_t, tls_destroy, void, 105: private_thread_value_t *this) 106: { 107: entry_t *entry; 108: 109: entry = thread_tls_remove(this); 110: if (entry) 111: { 112: thread_tls_cleanup(entry); 113: } 114: free(this); 115: } 116: 117: METHOD(thread_value_t, tls_set_index, void, 118: private_thread_value_t *this, void *val) 119: { 120: TlsSetValue(this->index, val); 121: } 122: 123: METHOD(thread_value_t, tls_get_index, void*, 124: private_thread_value_t *this) 125: { 126: return TlsGetValue(this->index); 127: } 128: 129: METHOD(thread_value_t, tls_destroy_index, void, 130: private_thread_value_t *this) 131: { 132: TlsFree(this->index); 133: free(this); 134: } 135: 136: /** 137: * Described in header. 138: */ 139: thread_value_t *thread_value_create(thread_cleanup_t cleanup) 140: { 141: private_thread_value_t *this; 142: DWORD index = TLS_OUT_OF_INDEXES; 143: 144: /* we have two implementations: Windows Tls* functions do not support 145: * callbacks and has limited instances. We use it nonetheless if possible, 146: * especially as leak detective relies on TLS, but we have to mangle 147: * leak detective state for TLS storage. */ 148: 149: if (!cleanup) 150: { 151: index = TlsAlloc(); 152: } 153: 154: if (index == TLS_OUT_OF_INDEXES) 155: { 156: INIT(this, 157: .public = { 158: .set = _tls_set, 159: .get = _tls_get, 160: .destroy = _tls_destroy, 161: }, 162: .cleanup = cleanup, 163: ); 164: } 165: else 166: { 167: INIT(this, 168: .public = { 169: .set = _tls_set_index, 170: .get = _tls_get_index, 171: .destroy = _tls_destroy_index, 172: }, 173: .index = index, 174: ); 175: } 176: 177: return &this->public; 178: }