diff options
-rw-r--r-- | Makefile | 1 | ||||
-rw-r--r-- | include/bls/bls.h | 4 | ||||
-rw-r--r-- | src/bls_c.cpp | 17 | ||||
-rw-r--r-- | test/bls_c384_test.cpp | 40 |
4 files changed, 62 insertions, 0 deletions
@@ -3,6 +3,7 @@ LIB_DIR=lib OBJ_DIR=obj EXE_DIR=bin CFLAGS += -std=c++11 +LDFLAGS += -lpthread SRC_SRC=bls.cpp bls_c.cpp TEST_SRC=bls_test.cpp bls_c384_test.cpp diff --git a/include/bls/bls.h b/include/bls/bls.h index f063ca6..2a9df84 100644 --- a/include/bls/bls.h +++ b/include/bls/bls.h @@ -50,6 +50,10 @@ typedef struct { @note init() is not thread safe */ BLS_DLL_API int blsInit(int curve, int maxUnitSize); +/* + wait for the finish of the first call blsInit() and do nothing +*/ +BLS_DLL_API int blsInitThreadSafe(int curve, int maxUnitSize); BLS_DLL_API size_t blsGetOpUnitSize(void); // return strlen(buf) if success else 0 diff --git a/src/bls_c.cpp b/src/bls_c.cpp index ccdc909..563ecc9 100644 --- a/src/bls_c.cpp +++ b/src/bls_c.cpp @@ -36,6 +36,23 @@ int blsInit(int curve, int maxUnitSize) return -1; } +#if CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11 +#include <mutex> +static std::mutex g_mutex; +static int g_curve = -1; + +int blsInitThreadSafe(int curve, int maxUnitSize) +{ + int ret = 0; + std::lock_guard<std::mutex> lock(g_mutex); + if (g_curve != curve) { + ret = blsInit(curve, maxUnitSize); + g_curve = curve; + } + return ret; +} +#endif + static inline const mclBnG1 *cast(const G1* x) { return (const mclBnG1*)x; } static inline const mclBnG2 *cast(const G2* x) { return (const mclBnG2*)x; } diff --git a/test/bls_c384_test.cpp b/test/bls_c384_test.cpp index 8c3761f..2e61e2c 100644 --- a/test/bls_c384_test.cpp +++ b/test/bls_c384_test.cpp @@ -62,6 +62,46 @@ void blsOrderTest(const char *curveOrder, const char *fieldOrder) CYBOZU_TEST_EQUAL(buf, fieldOrder); } +#if CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11 +#include <thread> +#include <vector> +struct Thread { + std::unique_ptr<std::thread> t; + Thread() : t() {} + ~Thread() + { + if (t) { + t->join(); + } + } + template<class F> + void run(F func, int p1, int p2) + { + t.reset(new std::thread(func, p1, p2)); + } +}; +CYBOZU_TEST_AUTO(multipleInit) +{ + const size_t n = 100; + { + std::vector<Thread> vt(n); + for (size_t i = 0; i < n; i++) { + vt[i].run(blsInitThreadSafe, mclBn_CurveFp254BNb, MCLBN_FP_UNIT_SIZE); + } + } + CYBOZU_TEST_EQUAL(blsGetOpUnitSize(), 4u); +#if MCLBN_FP_UNIT_SIZE == 6 + { + std::vector<Thread> vt(n); + for (size_t i = 0; i < n; i++) { + vt[i].run(blsInitThreadSafe, mclBn_CurveFp382_1, MCLBN_FP_UNIT_SIZE); + } + } + CYBOZU_TEST_EQUAL(blsGetOpUnitSize(), 6u); +#endif +} +#endif + CYBOZU_TEST_AUTO(all) { const int tbl[] = { |