summaryrefslogtreecommitdiff
path: root/src/htsnostatic.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/htsnostatic.h')
-rw-r--r--src/htsnostatic.h223
1 files changed, 223 insertions, 0 deletions
diff --git a/src/htsnostatic.h b/src/htsnostatic.h
new file mode 100644
index 0000000..6dbb072
--- /dev/null
+++ b/src/htsnostatic.h
@@ -0,0 +1,223 @@
+/* ------------------------------------------------------------ */
+/*
+HTTrack Website Copier, Offline Browser for Windows and Unix
+Copyright (C) Xavier Roche and other contributors
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+Important notes:
+
+- We hereby ask people using this source NOT to use it in purpose of grabbing
+emails addresses, or collecting any other private information on persons.
+This would disgrace our work, and spoil the many hours we spent on it.
+
+
+Please visit our Website: http://www.httrack.com
+*/
+
+
+/* ------------------------------------------------------------ */
+/* File: htsnostatic.c subroutines: */
+/* thread-safe routines for reentrancy */
+/* Author: Xavier Roche */
+/* ------------------------------------------------------------ */
+
+/*
+ Okay, with these routines, the engine should be fully reentrant (thread-safe)
+ All static references have been changed:
+
+ from
+ function foo() {
+ static bartype bar;
+ }
+ to:
+ function foo() {
+ bartype* bar;
+ NOSTATIC_RESERVE(bar, bartype, 1);
+ }
+*/
+
+#ifndef HTSNOSTATIC_DEFH
+#define HTSNOSTATIC_DEFH
+
+#include "htscore.h"
+#include "htsthread.h"
+
+/*
+#if USE_PTHREAD
+#if HTS_WIN
+#undef HTS_REENTRANT
+#else
+#define HTS_REENTRANT
+#endif
+#else
+#undef HTS_REENTRANT
+#endif
+*/
+
+#define HTS_VAR_MAIN_HASH 127
+
+/*
+ MutEx
+*/
+
+
+/* Magic per-thread variables functions
+
+ Example:
+ hts_lockvar();
+ hts_setvar("MyFoo", (long int)(void*)&foo);
+ hts_unlockvar();
+ ..
+ foo=(void*)(long int)hts_directgetvar("MyFoo");
+
+ Do not forget to initialize (hts_initvar()) the library once per thread
+*/
+int hts_initvar(void);
+int hts_freevar(void);
+int hts_resetvar(void);
+int hts_maylockvar(void);
+int hts_lockvar(void);
+int hts_unlockvar(void);
+
+int hts_setvar(char* name, long int value);
+int hts_getvar(char* name, long int* ptrvalue);
+long int hts_directgetvar(char* name);
+
+int hts_setblkvar(char* name, void* value);
+int hts_getblkvar(char* name, void** ptrvalue);
+void* hts_directgetblkvar(char* name);
+
+/* Internal */
+int hts_setextvar(char* name, long int value, int flag);
+int hts_getextvar(char* name, long int* ptrvalue, int flag);
+void hts_destroyvar(void* ptrkey);
+void hts_destroyvar_key(void* adr);
+
+/*
+ Ensure that the variable 'name' has 'nelts' of type 'type' reserved
+ fnc is an UNIQUE function name
+*/
+#define NOSTATIC_RESERVE(name, type, nelt) NOSTATIC_XRESERVE(name, type, nelt)
+
+/*
+ Note:
+ Yes, we first read the localInit flag variable without MutEx protection,
+ for optimization purpose, because the flag is set once initialization DONE.
+ If the first read fails, we *securely* re-check and initialize *if* necessary.
+ The abort() things should NEVER be called, and are here for safety reasons
+*/
+/*
+ function-specific static cKey:
+ cKey = { localKey, localInit }
+ || \
+ \/ \ ==1 upon initialization
+ thread variable
+ ||
+ \/
+ void*
+ ||
+ \/
+ 'thread-static' value
+
+ the function-specific static cKey is also referenced in the global
+ hashtable for free() purpose: (see hts_destroyvar())
+
+ global static key variable
+ 'hts_static_key'
+ ||
+ \/
+ thread variable
+ ||
+ \/
+ void*
+ ||
+ \/
+ hashtable
+ ||
+ \/
+ function-specific hash key
+ ||
+ \/
+ &cKey
+
+*/
+#if HTS_WIN
+
+/* Windows: handled by the compiler */
+#define NOSTATIC_XRESERVE(name, type, nelt) do { \
+ __declspec( thread ) static type thValue[nelt]; \
+ __declspec( thread ) int static initValue = 0; \
+ name = thValue; \
+ if (!initValue) { \
+ initValue = 1; \
+ memset(&thValue, 0, sizeof(thValue)); \
+ } \
+} while(0)
+
+#else
+
+/* Un*x : slightly more complex, we have to create a thread-key */
+typedef struct {
+ PTHREAD_KEY_TYPE localKey;
+ unsigned char localInit;
+} hts_NostaticComplexKey;
+#define NOSTATIC_XRESERVE(name, type, nelt) do { \
+static hts_NostaticComplexKey cKey={0,0}; \
+name = NULL; \
+if ( cKey.localInit ) { \
+ PTHREAD_KEY_GET(cKey.localKey, &name, type*); \
+} \
+if ( ( ! cKey.localInit ) || ( name == NULL ) ) { \
+ if (!hts_maylockvar()) { \
+ abort(); \
+ } \
+ hts_lockvar(); \
+ { \
+ { \
+ name = (type *) calloc((nelt), sizeof(type)); \
+ if (name == NULL) { \
+ abort(); \
+ } \
+ { \
+ char elt_name[64+8]; \
+ sprintf(elt_name, #name "_%d", (int) __LINE__); \
+ PTHREAD_KEY_CREATE(&(cKey.localKey), NULL); \
+ hts_setblkvar(elt_name, &cKey); \
+ } \
+ PTHREAD_KEY_SET(cKey.localKey, name, type*); \
+ name = NULL; \
+ PTHREAD_KEY_GET(cKey.localKey, &name, type*); \
+ if (name == NULL) { \
+ abort(); \
+ } \
+ if ( ! cKey.localInit ) { \
+ cKey.localInit = 1; \
+ } \
+ } \
+ } \
+ hts_unlockvar(); \
+} \
+else { \
+ PTHREAD_KEY_GET(cKey.localKey, &name, type*); \
+ if (name == NULL) { \
+ abort(); \
+ } \
+} \
+} while(0)
+#endif
+
+#endif