From 61290d4cf39bb2c6d53a23f2fc79f855b65aa371 Mon Sep 17 00:00:00 2001 From: SisMaker <1713699517@qq.com> Date: Mon, 29 Apr 2024 18:26:28 +0800 Subject: [PATCH] =?UTF-8?q?ft:=20=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 +- c_src/eNifLock/eNifLock.cc | 232 +++++++++---------------------------- src/eCLock.erl | 6 +- 3 files changed, 60 insertions(+), 183 deletions(-) diff --git a/README.md b/README.md index 3960e82..42e8c55 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,5 @@ Build 说明 ---- - eALock 基于atmoics - eCLock 基于c11 atomic - 两者性能基本一致 + eCLock 基于c++11 atomic + diff --git a/c_src/eNifLock/eNifLock.cc b/c_src/eNifLock/eNifLock.cc index af4da65..a042d66 100644 --- a/c_src/eNifLock/eNifLock.cc +++ b/c_src/eNifLock/eNifLock.cc @@ -1,14 +1,8 @@ #include "erl_nif.h" #include -#include -#include -#include -#include -#include using namespace std; const int LockSize = 2097152; -const int ScheduleCnt = 50; const int HashSalt = 786234121; atomic LockSlot[LockSize]; @@ -16,24 +10,32 @@ ERL_NIF_TERM atomTrue; ERL_NIF_TERM atomFalse; ERL_NIF_TERM atomUndefined; -int nifLoad(ErlNifEnv *env, void **priv_data, ERL_NIF_TERM) +typedef struct KeyNode_r { - atomTrue = enif_make_atom(env, "true"); - atomFalse = enif_make_atom(env, "false"); - atomUndefined = enif_make_atom(env, "undefined"); - return 0; -} + int KeyIx; + struct KeyNode_r *next; +} KeyNode; -bool isNotCurLocked(forward_list *locked, int KeyIx) +bool isNotLocked(KeyNode *LockedHead, int KeyIx) { - for (auto it : *locked) + KeyNode *temp = LockedHead; + while (temp != NULL) { - if (it == KeyIx) + if (temp->KeyIx == KeyIx) return false; + temp = temp->next; } return true; } +int nifLoad(ErlNifEnv *env, void **priv_data, ERL_NIF_TERM) +{ + atomTrue = enif_make_atom(env, "true"); + atomFalse = enif_make_atom(env, "false"); + atomUndefined = enif_make_atom(env, "undefined"); + return 0; +} + bool lockOne(ErlNifEnv *env, ErlNifPid *ThePid, int KeyIx, uint64_t Val) { uint64_t Expected = 0; @@ -62,179 +64,65 @@ bool lockOne(ErlNifEnv *env, ErlNifPid *ThePid, int KeyIx, uint64_t Val) } } -ERL_NIF_TERM tryLockSchedule(ErlNifEnv *env, int, const ERL_NIF_TERM argv[]) -{ - //enif_fprintf(stdout, "IMY************tryLocksSchedule00 %T \n", argv[0]); - set locked; - ERL_NIF_TERM allList = argv[1]; - ERL_NIF_TERM head; - int KeyIx; - while (enif_get_list_cell(env, allList, &head, &allList)) - { - enif_get_int(env, head, &KeyIx); - locked.insert(KeyIx); - } - - ErlNifPid ThePid; - enif_self(env, &ThePid); - uint64_t Val = (uint64_t)(ThePid.pid); - allList = argv[0]; - //enif_fprintf(stdout, "IMY************tryLocksSchedule222 %T \n", allList); - auto search = locked.end(); - while (enif_get_list_cell(env, allList, &head, &allList)) - { - KeyIx = enif_hash(ERL_NIF_INTERNAL_HASH, head, HashSalt) % LockSize; - //enif_fprintf(stdout, "IMY************tryLocksSchedule222000 %d \n", KeyIx); - search = locked.find(KeyIx); - if (search != locked.end()) - { - if (!lockOne(env, &ThePid, KeyIx, Val)) - { - goto Failed; - } - else - { - locked.insert(KeyIx); - } - } - } - //enif_fprintf(stdout, "IMY************tryLocksSchedule333 %T \n", allList); - return atomTrue; - -Failed: -{ - uint64_t RExpected; - for (auto it : locked) - { - RExpected = Val; - LockSlot[it].compare_exchange_strong(RExpected, 0); - } - return atomFalse; -} -} - ERL_NIF_TERM tryLock(ErlNifEnv *env, int, const ERL_NIF_TERM argv[]) { if (enif_is_list(env, argv[0])) { - // enif_fprintf(stdout, "IMY************tryLocks00 %T \n", argv[0]); ERL_NIF_TERM allList = argv[0]; ERL_NIF_TERM head; ErlNifPid ThePid; enif_self(env, &ThePid); uint64_t Val = (uint64_t)(ThePid.pid); int KeyIx; - //forward_list locked(15); - //list locked; - set locked; - // map locked; - unsigned int cnt = 0; - auto search = locked.end(); - // enif_fprintf(stdout, "IMY************tryLocks222 %T \n", allList); + KeyNode *LockedHead = NULL; while (enif_get_list_cell(env, allList, &head, &allList)) { - // enif_fprintf(stdout, "IMY************tryLocks222---- %T %T\n", head, allList); KeyIx = enif_hash(ERL_NIF_INTERNAL_HASH, head, HashSalt) % LockSize; - // enif_fprintf(stdout, "IMY************tryLocks222000 %d \n", KeyIx); - search = locked.find(KeyIx); - if (search != locked.end()) - //if (isNotCurLocked(&locked, KeyIx)) + KeyNode OneKeyNode = {KeyIx, LockedHead}; + if (isNotLocked(LockedHead, KeyIx)) { - if (!lockOne(env, &ThePid, KeyIx, Val)) + if (lockOne(env, &ThePid, KeyIx, Val)) { - goto Failed; + LockedHead = &OneKeyNode; } else { - // enif_fprintf(stdout, "IMY************tryLocks222111 %d \n", KeyIx); - //locked.push_front(KeyIx); - //locked.push_back(KeyIx); - locked.insert(KeyIx); - //locked.insert({KeyIx, 0}); - cnt++; - // enif_fprintf(stdout, "IMY************tryLocks222222 %d \n", cnt); - if (cnt >= ScheduleCnt) + uint64_t RExpected; + KeyNode *temp = LockedHead; + while (temp != NULL) { - goto Schedule; + RExpected = Val; + LockSlot[temp->KeyIx].compare_exchange_strong(RExpected, 0); + temp = temp->next; } } } } - // enif_fprintf(stdout, "IMY************tryLocks333 %T \n", allList); - return atomTrue; - - Schedule: - { - ERL_NIF_TERM ListLocked = enif_make_list(env, 0); - //for (auto it : locked) - // { - // enif_make_list_cell(env, enif_make_int(env, it), ListLocked); - //} - - ERL_NIF_TERM newargv[2] = {allList, ListLocked}; - //enif_fprintf(stdout, "IMY************tryLocks4444 %T \n", newargv); - return enif_schedule_nif(env, "tryLockSchedule", 0, &tryLockSchedule, 2, newargv); - } - - Failed: - { - //uint64_t RExpected; - //for (auto it : locked) - // { -//RExpected = Val; - // LockSlot[it].compare_exchange_strong(RExpected, 0); - // } - return atomFalse; - } -} -else -{ - int KeyIx; - KeyIx = enif_hash(ERL_NIF_INTERNAL_HASH, argv[0], HashSalt) % LockSize; - ErlNifPid ThePid; - enif_self(env, &ThePid); - uint64_t Val = (uint64_t)(ThePid.pid); - - if (lockOne(env, &ThePid, KeyIx, Val)) - { return atomTrue; } else { - return atomFalse; - } -} -} - -ERL_NIF_TERM releaseLockSchedule(ErlNifEnv *env, int, const ERL_NIF_TERM argv[]) -{ - ERL_NIF_TERM allList = argv[0]; - ERL_NIF_TERM head; - ErlNifPid ThePid; - enif_self(env, &ThePid); - uint64_t Expected = (uint64_t)(ThePid.pid); - uint64_t RExpected; - int KeyIx; - int isAllOk = 1; - enif_get_int(env, argv[1], &isAllOk); + int KeyIx; + KeyIx = enif_hash(ERL_NIF_INTERNAL_HASH, argv[0], HashSalt) % LockSize; + ErlNifPid ThePid; + enif_self(env, &ThePid); + uint64_t Val = (uint64_t)(ThePid.pid); - while (enif_get_list_cell(env, allList, &head, &allList)) - { - KeyIx = enif_hash(ERL_NIF_INTERNAL_HASH, head, HashSalt) % LockSize; - RExpected = Expected; - if (!LockSlot[KeyIx].compare_exchange_strong(RExpected, 0)) + if (lockOne(env, &ThePid, KeyIx, Val)) { - isAllOk = 0; + return atomTrue; + } + else + { + return atomFalse; } } - return isAllOk > 0 ? atomTrue : atomFalse; } ERL_NIF_TERM releaseLock(ErlNifEnv *env, int, const ERL_NIF_TERM argv[]) { if (enif_is_list(env, argv[0])) { - ERL_NIF_TERM allList = argv[0]; ERL_NIF_TERM head; ErlNifPid ThePid; @@ -242,7 +130,6 @@ ERL_NIF_TERM releaseLock(ErlNifEnv *env, int, const ERL_NIF_TERM argv[]) uint64_t Expected = (uint64_t)(ThePid.pid); uint64_t RExpected; int KeyIx; - unsigned int cnt = 0; int isAllOk = 1; while (enif_get_list_cell(env, allList, &head, &allList)) @@ -253,40 +140,27 @@ ERL_NIF_TERM releaseLock(ErlNifEnv *env, int, const ERL_NIF_TERM argv[]) { isAllOk = 0; } - cnt++; - if (cnt >= ScheduleCnt) - { - goto Schedule; - } } return isAllOk > 0 ? atomTrue : atomFalse; - - Schedule: - { - ERL_NIF_TERM ArgvAllOk = enif_make_int(env, isAllOk); - ERL_NIF_TERM newargv[2] = {allList, ArgvAllOk}; - //enif_fprintf(stdout, "IMY************tryLocks4444 %T \n", newargv); - return enif_schedule_nif(env, "releaseLockSchedule", ERL_NIF_DIRTY_JOB_CPU_BOUND, &releaseLockSchedule, 2, newargv); - } -} -else -{ - int KeyIx; - KeyIx = enif_hash(ERL_NIF_INTERNAL_HASH, argv[0], HashSalt) % LockSize; - ErlNifPid ThePid; - enif_self(env, &ThePid); - uint64_t Expected = (uint64_t)(ThePid.pid); - - if (LockSlot[KeyIx].compare_exchange_strong(Expected, 0)) - { - return atomTrue; } else { - return atomFalse; + int KeyIx; + KeyIx = enif_hash(ERL_NIF_INTERNAL_HASH, argv[0], HashSalt) % LockSize; + ErlNifPid ThePid; + enif_self(env, &ThePid); + uint64_t Expected = (uint64_t)(ThePid.pid); + + if (LockSlot[KeyIx].compare_exchange_strong(Expected, 0)) + { + return atomTrue; + } + else + { + return atomFalse; + } } } -} ERL_NIF_TERM getLockPid(ErlNifEnv *env, int, const ERL_NIF_TERM argv[]) { diff --git a/src/eCLock.erl b/src/eCLock.erl index 6bc9188..3b4818d 100644 --- a/src/eCLock.erl +++ b/src/eCLock.erl @@ -1,8 +1,12 @@ -module(eCLock). --include("eGLock.hrl"). -define(CASE(Cond, Then, That), case Cond of true -> Then; _ -> That end). +%% 默认超时时间单位:Ms +-define(LockTimeOut, 5000). +%% 超时重试时间单位:Ms +-define(ReTryTime, 3). + -export([ tryLock/1 , tryLock/2