1
0
mirror of https://github.com/ohwgiles/laminar.git synced 2024-10-27 20:34:20 +00:00

implement general-purpose locks

This commit is contained in:
Oliver Giles 2017-08-10 07:40:30 +03:00
parent f42325b472
commit ab99af7ca7
3 changed files with 49 additions and 0 deletions

View File

@ -158,6 +158,14 @@ int main(int argc, char** argv) {
auto response = req.send().wait(waitScope); auto response = req.send().wait(waitScope);
if(response.getResult() != LaminarCi::JobResult::SUCCESS) if(response.getResult() != LaminarCi::JobResult::SUCCESS)
return EFAILED; return EFAILED;
} else if(strcmp(argv[1], "lock") == 0) {
auto req = laminar.lockRequest();
req.setLockName(argv[2]);
req.send().wait(waitScope);
} else if(strcmp(argv[1], "release") == 0) {
auto req = laminar.releaseRequest();
req.setLockName(argv[2]);
req.send().wait(waitScope);
} else { } else {
fprintf(stderr, "Unknown comand %s\n", argv[1]); fprintf(stderr, "Unknown comand %s\n", argv[1]);
return EINVAL; return EINVAL;

View File

@ -6,6 +6,8 @@ interface LaminarCi {
start @1 (jobName :Text, params :List(JobParam)) -> (result :JobResult); start @1 (jobName :Text, params :List(JobParam)) -> (result :JobResult);
pend @2 (jobName :Text, buildNum :UInt32) -> (result :JobResult); pend @2 (jobName :Text, buildNum :UInt32) -> (result :JobResult);
set @3 (jobName :Text, buildNum :UInt32, param :JobParam) -> (result :MethodResult); set @3 (jobName :Text, buildNum :UInt32, param :JobParam) -> (result :MethodResult);
lock @4 (lockName :Text) -> ();
release @5 (lockName :Text) -> ();
struct JobParam { struct JobParam {
name @0 :Text; name @0 :Text;

View File

@ -75,6 +75,18 @@ LaminarCi::JobResult fromRunState(RunState state) {
// As such, it implements the pure virtual interface generated from // As such, it implements the pure virtual interface generated from
// laminar.capnp with calls to the LaminarInterface // laminar.capnp with calls to the LaminarInterface
class RpcImpl : public LaminarCi::Server { class RpcImpl : public LaminarCi::Server {
private:
struct Lock {
Lock() : paf(kj::newPromiseAndFulfiller<void>()) {}
void release() {
paf.fulfiller->fulfill();
}
kj::Promise<void> takePromise() { return std::move(paf.promise); }
private:
kj::PromiseFulfillerPair<void> paf;
};
public: public:
RpcImpl(LaminarInterface& l) : RpcImpl(LaminarInterface& l) :
LaminarCi::Server(), LaminarCi::Server(),
@ -143,9 +155,36 @@ public:
return kj::READY_NOW; return kj::READY_NOW;
} }
// Take a named lock
kj::Promise<void> lock(LockContext context) override {
std::string lockName = context.getParams().getLockName();
LLOG(INFO, "RPC lock", lockName);
auto& lockList = locks[lockName];
lockList.emplace_back(Lock{});
if(lockList.size() == 1)
lockList.front().release();
return lockList.back().takePromise();
}
// Release a named lock
kj::Promise<void> release(ReleaseContext context) override {
std::string lockName = context.getParams().getLockName();
LLOG(INFO, "RPC release", lockName);
auto& lockList = locks[lockName];
if(lockList.size() == 0) {
LLOG(INFO, "Attempt to release unheld lock", lockName);
return kj::READY_NOW;
}
lockList.erase(lockList.begin());
if(lockList.size() > 0)
lockList.front().release();
return kj::READY_NOW;
}
private: private:
LaminarInterface& laminar; LaminarInterface& laminar;
kj::LowLevelAsyncIoProvider* asyncio; kj::LowLevelAsyncIoProvider* asyncio;
std::unordered_map<std::string, std::list<Lock>> locks;
}; };