Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 26 additions & 18 deletions indra/alscript/lsl/allslservice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "allsltraits.h"
#include "alscriptlexicon.h"

#include "llcoros.h"
#include "llfile.h"

#include "Luau/LSLBuiltins.h"
Expand All @@ -47,11 +48,13 @@

#include <algorithm>
#include <cstring>
#include <mutex>
#include <memory>
#include <optional>
#include <set>
#include <sstream>

#include LLCOROS_MUTEX_HEADER

namespace
{
std::atomic<bool> sBuiltinsLoaded{ false };
Expand Down Expand Up @@ -1110,33 +1113,38 @@ namespace
}

// The builtins of a kind: its functions, or its constants; none of any
// other kind.
const std::vector<std::string>& builtinNames(Tailslide::LSLSymbolTable* builtins, Tailslide::LSLSymbolType wanted)
{
static std::mutex lock;
static Tailslide::LSLSymbolTable* listed = nullptr;
static size_t count = 0;
static std::vector<std::string> functions;
static std::vector<std::string> variables;
static const std::vector<std::string> none;
const std::lock_guard<std::mutex> guard(lock);
// other kind. Asked on any thread, and in a coroutine: each list is
// handed out shared, and made anew rather than changed where the table
// changes, so that one being read outlives its place here.
typedef std::shared_ptr<const std::vector<std::string>> names_t;
names_t builtinNames(Tailslide::LSLSymbolTable* builtins, Tailslide::LSLSymbolType wanted)
{
static LLCoros::Mutex lock;
static Tailslide::LSLSymbolTable* listed = nullptr;
static size_t count = 0;
static names_t functions = std::make_shared<const std::vector<std::string>>();
static names_t variables = functions;
static const names_t none = functions;
const LLCoros::LockType guard(lock);
if (builtins && (builtins != listed || builtins->getMap().size() != count))
{
functions.clear();
variables.clear();
auto made_functions = std::make_shared<std::vector<std::string>>();
auto made_variables = std::make_shared<std::vector<std::string>>();
for (auto& [name, symbol] : builtins->getMap())
{
if (symbol->getSymbolType() == Tailslide::SYM_FUNCTION)
{
functions.emplace_back(symbol->getName());
made_functions->emplace_back(symbol->getName());
}
else if (symbol->getSymbolType() == Tailslide::SYM_VARIABLE)
{
variables.emplace_back(symbol->getName());
made_variables->emplace_back(symbol->getName());
}
}
listed = builtins;
count = builtins->getMap().size();
functions = std::move(made_functions);
variables = std::move(made_variables);
listed = builtins;
count = builtins->getMap().size();
}
return wanted == Tailslide::SYM_FUNCTION ? functions : wanted == Tailslide::SYM_VARIABLE ? variables : none;
}
Expand Down Expand Up @@ -1661,7 +1669,7 @@ ALScriptProblems ALLSLService::check(std::string_view source, bool mono)
// the handler it is in, nor a variable to a label.
const Tailslide::LSLSymbolType wanted = kindWantedAt(script, problem.line, problem.column);
ALScriptFixes::offerNames(problem, lines, problem.args[0], namesAt(script, problem.line, problem.column, wanted),
builtinNames(parser.context.builtins, wanted));
*builtinNames(parser.context.builtins, wanted));
}
}
}
Expand Down
12 changes: 7 additions & 5 deletions indra/alscript/luau/alluauconfigscript.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,17 @@
#include "Luau/Compiler.h"
#include "lua.h"
#include "lualib.h"
#include "llcoros.h"

#include <algorithm>
#include <string_view>
#include <chrono>
#include <cstdlib>
#include <memory>
#include <mutex>
#include <vector>

#include LLCOROS_MUTEX_HEADER

LUAU_FASTFLAG(LuauIntegerLibrary)

namespace
Expand Down Expand Up @@ -377,7 +379,7 @@ namespace
// than its text: a thread held up elsewhere would otherwise see a good
// configuration refused until the text changed. Kept a while all the
// same, not run again at every ask, so that one that never ends costs
// its time only so often.
// its time only so often. Asked on any thread, and in a coroutine.
struct Ran
{
std::string source;
Expand All @@ -387,15 +389,15 @@ namespace
};
constexpr size_t RAN_KEPT = 32;
constexpr std::chrono::seconds LATE_KEPT = std::chrono::seconds(10);
std::mutex sRanMutex;
LLCoros::Mutex sRanMutex;
std::vector<Ran> sRan;
}

// static
bool ALLuauConfigScript::asLuaurc(const std::string& source, std::string& json, std::string& error)
{
{
const std::lock_guard<std::mutex> lock(sRanMutex);
const LLCoros::LockType lock(sRanMutex);
const auto found = std::find_if(sRan.begin(), sRan.end(), [&source](const Ran& ran) { return ran.source == source; });
if (found != sRan.end() && std::chrono::steady_clock::now() < found->until)
{
Expand Down Expand Up @@ -423,7 +425,7 @@ bool ALLuauConfigScript::asLuaurc(const std::string& source, std::string& json,
{
ran.until = std::chrono::steady_clock::now() + LATE_KEPT;
}
const std::lock_guard<std::mutex> lock(sRanMutex);
const LLCoros::LockType lock(sRanMutex);
sRan.insert(sRan.begin(), std::move(ran));
if (sRan.size() > RAN_KEPT)
{
Expand Down
17 changes: 10 additions & 7 deletions indra/alscript/luau/alluauexports.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@
#include "Luau/Ast.h"
#include "Luau/Parser.h"
#include "alscriptlexicon.h"
#include "llcoros.h"

#include <algorithm>
#include <deque>
#include <functional>
#include <mutex>

#include LLCOROS_MUTEX_HEADER

namespace
{
Expand Down Expand Up @@ -219,7 +221,8 @@ namespace ALLuauExports
namespace
{
// What each module checked was found to export, by its key and its
// text's length and hash, the latest last.
// text's length and hash, the latest last: kept and asked on any
// thread, and in a coroutine.
struct Checked
{
std::string key;
Expand All @@ -228,14 +231,14 @@ namespace ALLuauExports
std::vector<std::string> names;
};
constexpr size_t CHECKED_KEPT = 256;
std::mutex sCheckedMutex;
LLCoros::Mutex sCheckedMutex;
std::deque<Checked> sChecked;
}

void checked(const std::string& key, std::string_view text, std::vector<std::string> names)
{
const size_t hash = std::hash<std::string_view>()(text);
const std::lock_guard<std::mutex> lock(sCheckedMutex);
const size_t hash = std::hash<std::string_view>()(text);
const LLCoros::LockType lock(sCheckedMutex);
sChecked.erase(std::remove_if(sChecked.begin(), sChecked.end(), [&key](const Checked& one) { return one.key == key; }), sChecked.end());
sChecked.push_back({ key, text.size(), hash, std::move(names) });
if (sChecked.size() > CHECKED_KEPT)
Expand All @@ -246,8 +249,8 @@ namespace ALLuauExports

std::optional<std::vector<std::string>> checkedOf(const std::string& key, std::string_view text)
{
const size_t hash = std::hash<std::string_view>()(text);
const std::lock_guard<std::mutex> lock(sCheckedMutex);
const size_t hash = std::hash<std::string_view>()(text);
const LLCoros::LockType lock(sCheckedMutex);
for (const Checked& one : sChecked)
{
if (one.key == key && one.size == text.size() && one.hash == hash)
Expand Down
25 changes: 14 additions & 11 deletions indra/alscript/masters/almasterindex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,15 @@
#include "alserialworker.h"
#include "aluploadheader.h"
#include "fsyspath.h"
#include "llcoros.h"
#include "llsdserialize.h"

#include <condition_variable>
#include <filesystem>
#include <mutex>
#include <sstream>

#include LLCOROS_MUTEX_HEADER
#include LLCOROS_CONDVAR_HEADER

namespace
{
// The target a notecard's text is hashed under.
Expand All @@ -61,29 +63,30 @@ namespace
// all of it -- and whether one is being written now, by the writer's thread
// or by the index's. One write at a time, whichever thread makes it, so
// that two never meet in the file put beside the index on the way. What
// could not be written waits still, to be tried again.
// could not be written waits still, to be tried again. The index's thread
// may be the main one, and a coroutine there what waits.
struct ALMasterIndex::Writer
{
struct Text
{
std::string path;
std::string text;
};
std::mutex mutex;
std::condition_variable changed;
std::optional<Text> waiting;
LLCoros::Mutex mutex;
LLCoros::ConditionVariable changed;
std::optional<Text> waiting;
// Whether what waits is what a write of failed, kept for the next
// drain: the next change's, which is all of it and more, or a flush's.
bool failed = false;
bool busy = false;
bool failed = false;
bool busy = false;

// What waits written, and what comes meanwhile, on whichever thread
// asks: one being written already by another is waited for first, so
// that all that was handed over is on the disk as this returns. One
// that cannot be written is tried once here, said, and left waiting.
void drain()
{
std::unique_lock<std::mutex> lock(mutex);
LLCoros::LockType lock(mutex);
for (;;)
{
changed.wait(lock, [this] { return !busy; });
Expand Down Expand Up @@ -123,7 +126,7 @@ struct ALMasterIndex::Writer
// for first, so that the answer is the write's.
bool unwritten()
{
std::unique_lock<std::mutex> lock(mutex);
LLCoros::LockType lock(mutex);
changed.wait(lock, [this] { return !busy; });
return failed;
}
Expand Down Expand Up @@ -534,7 +537,7 @@ void ALMasterIndex::handOver()
mDirty = false;
std::ostringstream out;
LLSDSerialize::toPrettyXML(mLinks.toLLSD(), out);
const std::lock_guard<std::mutex> lock(mWriter->mutex);
const LLCoros::LockType lock(mWriter->mutex);
mWriter->waiting = Writer::Text{ mPath, out.str() };
mWriter->failed = false;
}
Expand Down
17 changes: 10 additions & 7 deletions indra/alscript/preprocessor/alscriptjoblane.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,17 @@

#pragma once

#include "llcoros.h"
#include "llerror.h"

#include <deque>
#include <exception>
#include <functional>
#include <memory>
#include <mutex>
#include <string>

#include LLCOROS_MUTEX_HEADER

// What waits for a worker, on the worker's side: it takes the next itself
// as each ends, rather than waiting a frame for the main thread to hand it
// over. A run before any check; a check of a script whose later check is
Expand All @@ -59,7 +61,7 @@ class ALScriptJobLane
// started on drain(). Nothing, once closed.
bool put(Queued queued, const taking_t& taking)
{
std::lock_guard<std::mutex> guard(mLock);
LLCoros::LockType guard(mLock);
if (mClosed)
{
return false;
Expand Down Expand Up @@ -106,7 +108,7 @@ class ALScriptJobLane
{
std::function<void()> work;
{
std::lock_guard<std::mutex> guard(mLock);
LLCoros::LockType guard(mLock);
mRunning.reset();
std::deque<Queued>& from = !mRuns.empty() ? mRuns : mChecks;
if (mClosed || from.empty())
Expand Down Expand Up @@ -139,7 +141,7 @@ class ALScriptJobLane
// starts it again.
void notStarted()
{
std::lock_guard<std::mutex> guard(mLock);
LLCoros::LockType guard(mLock);
mDraining = false;
mRuns.clear();
mChecks.clear();
Expand All @@ -148,20 +150,21 @@ class ALScriptJobLane
// Nothing more taken, and what waits let go of; kept closed.
void close()
{
std::lock_guard<std::mutex> guard(mLock);
LLCoros::LockType guard(mLock);
mClosed = true;
mRuns.clear();
mChecks.clear();
}

size_t waiting()
{
std::lock_guard<std::mutex> guard(mLock);
LLCoros::LockType guard(mLock);
return mRuns.size() + mChecks.size();
}

private:
std::mutex mLock;
// The main thread's side may be a coroutine's.
LLCoros::Mutex mLock;
std::deque<Queued> mRuns;
std::deque<Queued> mChecks;
bool mDraining = false;
Expand Down
2 changes: 2 additions & 0 deletions indra/llcommon/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ target_sources(
alsanitizer.h
alsavehistory.h
alscratcharena.h
alsharedmutex.h
alsimd.h
alwatchedfile.h
always_return.h
Expand Down Expand Up @@ -316,6 +317,7 @@ if(AL_BUILD_TESTS)
tests/alsavehistory_test.cpp
tests/alscratcharena_test.cpp
tests/alserialworker_test.cpp
tests/alsharedmutex_test.cpp
tests/alsimd_test.cpp
tests/alwatchedfile_test.cpp
tests/apply_test.cpp
Expand Down
Loading
Loading