| @@ -14,13 +14,6 @@ namespace rack { | |||||
| namespace plugin { | namespace plugin { | ||||
| struct Update { | |||||
| std::string pluginSlug; | |||||
| std::string version; | |||||
| std::string changelogUrl; | |||||
| }; | |||||
| void init(); | void init(); | ||||
| void destroy(); | void destroy(); | ||||
| void logIn(const std::string &email, const std::string &password); | void logIn(const std::string &email, const std::string &password); | ||||
| @@ -36,6 +29,13 @@ std::string normalizeTag(const std::string &tag); | |||||
| bool isSlugValid(const std::string &slug); | bool isSlugValid(const std::string &slug); | ||||
| struct Update { | |||||
| std::string pluginSlug; | |||||
| std::string version; | |||||
| std::string changelogUrl; | |||||
| }; | |||||
| extern const std::set<std::string> allowedTags; | extern const std::set<std::string> allowedTags; | ||||
| extern std::vector<Plugin*> plugins; | extern std::vector<Plugin*> plugins; | ||||
| @@ -11,7 +11,9 @@ namespace rack { | |||||
| namespace random { | namespace random { | ||||
| /** Seeds the RNG with the current time */ | |||||
| /** Initializes the thread-local RNG state. | |||||
| Must call per-thread, otherwise the RNG will always return 0. | |||||
| */ | |||||
| void init(); | void init(); | ||||
| /** Returns a uniform random uint32_t from 0 to UINT32_MAX */ | /** Returns a uniform random uint32_t from 0 to UINT32_MAX */ | ||||
| uint32_t u32(); | uint32_t u32(); | ||||
| @@ -150,6 +150,7 @@ struct EngineWorker { | |||||
| void start() { | void start() { | ||||
| thread = std::thread([&] { | thread = std::thread([&] { | ||||
| random::init(); | |||||
| run(); | run(); | ||||
| }); | }); | ||||
| } | } | ||||
| @@ -436,7 +437,10 @@ static void Engine_run(Engine *that) { | |||||
| void Engine::start() { | void Engine::start() { | ||||
| internal->running = true; | internal->running = true; | ||||
| internal->thread = std::thread(Engine_run, this); | |||||
| internal->thread = std::thread([&] { | |||||
| random::init(); | |||||
| Engine_run(this); | |||||
| }); | |||||
| } | } | ||||
| void Engine::stop() { | void Engine::stop() { | ||||
| @@ -11,7 +11,7 @@ namespace random { | |||||
| // xoroshiro128+ | // xoroshiro128+ | ||||
| // from http://xoroshiro.di.unimi.it/xoroshiro128plus.c | // from http://xoroshiro.di.unimi.it/xoroshiro128plus.c | ||||
| static uint64_t xoroshiro128plus_state[2] = {}; | |||||
| thread_local uint64_t xoroshiro128plus_state[2]; | |||||
| static uint64_t rotl(const uint64_t x, int k) { | static uint64_t rotl(const uint64_t x, int k) { | ||||
| return (x << k) | (x >> (64 - k)); | return (x << k) | (x >> (64 - k)); | ||||
| @@ -30,8 +30,6 @@ static uint64_t xoroshiro128plus_next(void) { | |||||
| } | } | ||||
| void init() { | void init() { | ||||
| // Only allow the seed to be initialized once during the lifetime of the program. | |||||
| assert(xoroshiro128plus_state[0] == 0 && xoroshiro128plus_state[1] == 0); | |||||
| struct timeval tv; | struct timeval tv; | ||||
| gettimeofday(&tv, NULL); | gettimeofday(&tv, NULL); | ||||
| xoroshiro128plus_state[0] = tv.tv_sec; | xoroshiro128plus_state[0] = tv.tv_sec; | ||||