#include "StateTokenServer.h" #include namespace resource_api { // maybe it would be good to make this part of state token or friend, to be able to directly access the value StreamBase& operator <<(StreamBase& left, KeyValueReference kv) { if(left.serialise()) { // have to make a variable, to be able to pass it by reference // (cant pass return value of a function by refernce to another function) int value = kv.value.getValue(); left << makeKeyValueReference(kv.key, value); } else { int value; left << makeKeyValueReference(kv.key, value); kv.value = StateToken(value); } return left; } StreamBase& operator<<(StreamBase& left, StateToken& token) { if(left.serialise()) { // have to make a variable, to be able to pass it by reference // (cant pass return value of a function by refernce to another function) int value = token.getValue(); left << value; } else { int value; left << value; token = StateToken(value); } return left; } bool operator==(const StateToken& left, const StateToken& right) { if(left.getValue() == right.getValue()) { return true; } else { return false; } } StateTokenServer::StateTokenServer(): mMtx("StateTokenServer mMtx"), mNextToken(1), mClientsMtx("StateTokenServer mClientsMtx") { addResourceHandler("*", this, &StateTokenServer::handleWildcard); } StateToken StateTokenServer::getNewToken() { RsStackMutex stack(mMtx); /********** STACK LOCKED MTX ******/ return locked_getNewToken(); } void StateTokenServer::discardToken(StateToken token) { RsStackMutex stack(mMtx); /********** STACK LOCKED MTX ******/ locked_discardToken(token); } void StateTokenServer::replaceToken(StateToken &token) { RsStackMutex stack(mMtx); /********** STACK LOCKED MTX ******/ locked_discardToken(token); token = locked_getNewToken(); } void StateTokenServer::registerTickClient(Tickable *c) { // extra service: tick it to let it init its ticking stuff c->tick(); // avoid double registration unregisterTickClient(c); RsStackMutex stack(mClientsMtx); /********** STACK LOCKED MTX ***********/ mTickClients.push_back(c); } void StateTokenServer::unregisterTickClient(Tickable *c) { RsStackMutex stack(mClientsMtx); /********** STACK LOCKED MTX ***********/ std::vector::iterator vit = std::find(mTickClients.begin(), mTickClients.end(), c); if(vit != mTickClients.end()) mTickClients.erase(vit); } void StateTokenServer::handleWildcard(Request &req, Response &resp) { { RsStackMutex stack(mClientsMtx); /********** STACK LOCKED MTX ***********/ for(std::vector::iterator vit = mTickClients.begin(); vit != mTickClients.end(); ++vit) { (*vit)->tick(); } } RsStackMutex stack(mMtx); /********** STACK LOCKED MTX ******/ // want to lookpup many tokens at once, return a list of invalid tokens // TODO: make generic list serialiser/deserialiser while(req.mStream.hasMore()) { StateToken token; req.mStream << token; // lookup if token is valid if(std::find(mValidTokens.begin(), mValidTokens.end(), token) == mValidTokens.end()) { // if invalid, add to response list resp.mDataStream << token; } } resp.setOk(); } StateToken StateTokenServer::locked_getNewToken() { StateToken token(mNextToken); mValidTokens.push_back(token); mNextToken++; if(mNextToken == 0) // 0 is a reserved value, don't ever use it mNextToken = 1; return token; } void StateTokenServer::locked_discardToken(StateToken token) { std::vector::iterator toDelete = std::find(mValidTokens.begin(), mValidTokens.end(), token); if(toDelete != mValidTokens.end()) { mValidTokens.erase(toDelete); } } } // namespace resource_api