diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 00000000..041a55e0 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,78 @@ +#taken from https://gist.github.com/airglow923/1fa3bda42f2b193920d7f46ee8345e04 +CheckOptions: + - key: readability-identifier-naming.ClassCase + value: CamelCase + - key: readability-identifier-naming.ClassMemberCase + value: lower_case + - key: readability-identifier-naming.ConstexprVariableCase + value: lower_case + #no enforce + - key: readability-identifier-naming.ConstexprVariablePrefix + value: "" + - key: readability-identifier-naming.EnumCase + value: CamelCase + - key: readability-identifier-naming.EnumConstantCase + value: CamelCase + #no enforce + - key: readability-identifier-naming.EnumConstantPrefix + value: "" + - key: readability-identifier-naming.FunctionCase + value: CamelCase + - key: readability-identifier-naming.GlobalConstantCase + value: CamelCase + #no enforce + - key: readability-identifier-naming.GlobalConstantPrefix + value: "" + - key: readability-identifier-naming.StaticConstantCase + value: CamelCase + #no enforce + - key: readability-identifier-naming.StaticConstantPrefix + value: "" + - key: readability-identifier-naming.StaticVariableCase + value: lower_case + - key: readability-identifier-naming.MacroDefinitionCase + value: UPPER_CASE + - key: readability-identifier-naming.MacroDefinitionIgnoredRegexp + value: "^[A-Z]+(_[A-Z]+)*_$" + # when enabling case it needs also suffix defined(and (_)? doesn't help) + # - key: readability-identifier-naming.MemberCase + # value: lower_case + # - key: readability-identifier-naming.MemberSuffix + # value: "" + + - key: readability-identifier-naming.NamespaceCase + value: lower_case + - key: readability-identifier-naming.ParameterCase + value: lower_case + - key: readability-identifier-naming.TypeAliasCase + value: CamelCase + - key: readability-identifier-naming.TypedefCase + value: CamelCase + - key: readability-identifier-naming.VariableCase + value: lower_case + - key: readability-identifier-naming.IgnoreMainLikeFunctions + value: 1 + +Checks: " + -*, + readability-identifier-naming, + cppcoreguidelines-avoid-goto, + cppcoreguidelines-explicit-virtual-functions, + cppcoreguidelines-no-malloc, + cppcoreguidelines-pro-bounds-pointer-arithmetic, + cppcoreguidelines-pro-type-static-cast-downcast, + cppcoreguidelines-pro-type-union-access, + cppcoreguidelines-missing-std-forward, + modernize-avoid-c-arrays, + modernize-use-emplace, + modernize-use-override, + modernize-use-nullptr, + modernize-deprecated-headers, + modernize-use-constraints, + performance-trivially-destructible, + performance-inefficient-vector-operation, + performance-inefficient-algorithm, + performance-for-range-copy, + misc-static-assert, + misc-redundant-expression" +WarningsAsErrors: "*" diff --git a/codegen/coyieldpass.cpp b/codegen/coyieldpass.cpp index d97589aa..63a28d88 100644 --- a/codegen/coyieldpass.cpp +++ b/codegen/coyieldpass.cpp @@ -136,9 +136,11 @@ struct CoYieldInserter { InsertCall(filt_entry, builder, true); // Invoke instruction has unwind/normal ends so we need handle it if (invoke) { - builder.SetInsertPoint(invoke->getNormalDest()->getFirstInsertionPt()); + builder.SetInsertPoint( + invoke->getNormalDest()->getFirstInsertionPt()); InsertCall(filt_entry, builder, false); - builder.SetInsertPoint(invoke->getUnwindDest()->getFirstInsertionPt()); + builder.SetInsertPoint( + invoke->getUnwindDest()->getFirstInsertionPt()); InsertCall(filt_entry, builder, false); } else { builder.SetInsertPoint(call->getNextNode()); @@ -212,7 +214,7 @@ struct CoYieldInserter { Constant *str_const = ConstantDataArray::getString(m.getContext(), filt.print_name, true); auto zero = ConstantInt::get(Type::getInt32Ty(m.getContext()), 0); - Constant *ind[] = {zero, zero}; + std::array ind = {zero, zero}; GlobalVariable *global = new GlobalVariable( m, str_const->getType(), true, GlobalValue::PrivateLinkage, str_const); auto ptr = diff --git a/codegen/yieldpass.cpp b/codegen/yieldpass.cpp index 51ad0873..295fc4de 100644 --- a/codegen/yieldpass.cpp +++ b/codegen/yieldpass.cpp @@ -9,21 +9,21 @@ using Builder = IRBuilder<>; using FunIndex = std::set>; -const StringRef nonatomic_attr = "ltest_nonatomic"; +const StringRef NonatomicAttr = "ltest_nonatomic"; -FunIndex CreateFunIndex(const Module &M) { +FunIndex CreateFunIndex(const Module &m) { FunIndex index{}; - for (auto it = M.global_begin(); it != M.global_end(); ++it) { + for (auto it = m.global_begin(); it != m.global_end(); ++it) { if (it->getName() != "llvm.global.annotations") { continue; } - auto *CA = dyn_cast(it->getOperand(0)); - for (auto o_it = CA->op_begin(); o_it != CA->op_end(); ++o_it) { - auto *CS = dyn_cast(o_it->get()); - auto *fun = dyn_cast(CS->getOperand(0)); - auto *AnnotationGL = dyn_cast(CS->getOperand(1)); + auto *ca = dyn_cast(it->getOperand(0)); + for (auto o_it = ca->op_begin(); o_it != ca->op_end(); ++o_it) { + auto *cs = dyn_cast(o_it->get()); + auto *fun = dyn_cast(cs->getOperand(0)); + auto *annotation_gl = dyn_cast(cs->getOperand(1)); auto annotation = - dyn_cast(AnnotationGL->getInitializer()) + dyn_cast(annotation_gl->getInitializer()) ->getAsCString(); index.insert({annotation, fun->getName()}); } @@ -37,25 +37,25 @@ bool HasAttribute(const FunIndex &index, const StringRef name, } struct YieldInserter { - YieldInserter(Module &M) : M(M) { - CoroYieldF = M.getOrInsertFunction( - "CoroYield", FunctionType::get(Type::getVoidTy(M.getContext()), {})); + YieldInserter(Module &m) : M(m) { + CoroYieldF = m.getOrInsertFunction( + "CoroYield", FunctionType::get(Type::getVoidTy(m.getContext()), {})); } void Run(const FunIndex &index) { - for (auto &F : M) { - if (IsTarget(F.getName(), index)) { - InsertYields(F, index); + for (auto &f : M) { + if (IsTarget(f.getName(), index)) { + InsertYields(f, index); - errs() << "yields inserted to the " << F.getName() << "\n"; - errs() << F << "\n"; + errs() << "yields inserted to the " << f.getName() << "\n"; + errs() << f << "\n"; } } } private: bool IsTarget(const StringRef fun_name, const FunIndex &index) { - return HasAttribute(index, fun_name, nonatomic_attr); + return HasAttribute(index, fun_name, NonatomicAttr); } bool NeedInterrupt(Instruction *insn, const FunIndex &index) { @@ -67,13 +67,13 @@ struct YieldInserter { return false; } - void InsertYields(Function &F, const FunIndex &index) { - Builder Builder(&*F.begin()); - for (auto &B : F) { - for (auto it = B.begin(); std::next(it) != B.end(); ++it) { + void InsertYields(Function &f, const FunIndex &index) { + Builder builder(&*f.begin()); + for (auto &b : f) { + for (auto it = b.begin(); std::next(it) != b.end(); ++it) { if (NeedInterrupt(&*it, index) && !ItsYieldInst(&*std::next(it))) { - Builder.SetInsertPoint(&*std::next(it)); - Builder.CreateCall(CoroYieldF, {})->getIterator(); + builder.SetInsertPoint(&*std::next(it)); + builder.CreateCall(CoroYieldF, {})->getIterator(); ++it; } } @@ -99,7 +99,7 @@ struct YieldInserter { namespace { struct YieldInsertPass final : public PassInfoMixin { - PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM) { + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM) { // NOLINT auto fun_index = CreateFunIndex(M); YieldInserter gen{M}; @@ -116,10 +116,10 @@ llvmGetPassPluginInfo() { return {.APIVersion = LLVM_PLUGIN_API_VERSION, .PluginName = "yield_insert", .PluginVersion = "v0.1", - .RegisterPassBuilderCallbacks = [](PassBuilder &PB) { - PB.registerPipelineStartEPCallback( - [](ModulePassManager &MPM, OptimizationLevel Level) { - MPM.addPass(YieldInsertPass()); + .RegisterPassBuilderCallbacks = [](PassBuilder &pb) { + pb.registerPipelineStartEPCallback( + [](ModulePassManager &mpm, OptimizationLevel level) { + mpm.addPass(YieldInsertPass()); }); }}; } \ No newline at end of file diff --git a/runtime/generators.cpp b/runtime/generators.cpp index f4049c69..c744caad 100644 --- a/runtime/generators.cpp +++ b/runtime/generators.cpp @@ -7,11 +7,11 @@ namespace generators { std::shared_ptr generated_token{}; // Generates empty arguments. -std::tuple<> genEmpty(size_t thread_num) { return std::tuple<>(); } +std::tuple<> GenEmpty(size_t thread_num) { return std::tuple<>(); } // Generates runtime token. // Can be called only once per task creation. -std::tuple> genToken(size_t thread_num) { +std::tuple> GenToken(size_t thread_num) { assert(!generated_token && "forgot to reset generated_token"); generated_token = std::make_shared(); return {generated_token}; diff --git a/runtime/include/generators.h b/runtime/include/generators.h index 15188c33..00d0145a 100644 --- a/runtime/include/generators.h +++ b/runtime/include/generators.h @@ -12,14 +12,14 @@ extern std::shared_ptr generated_token; // Makes single argument from the value. template -auto makeSingleArg(T&& arg) { - using arg_type = typename std::remove_reference::type; - return std::tuple{std::forward(arg)}; +auto MakeSingleArg(T&& arg) { + using ArgType = typename std::remove_reference::type; + return std::tuple{std::forward(arg)}; } -std::tuple<> genEmpty(size_t thread_num); +std::tuple<> GenEmpty(size_t thread_num); -std::tuple> genToken(size_t thread_num); +std::tuple> GenToken(size_t thread_num); } // namespace generators diff --git a/runtime/include/lib.h b/runtime/include/lib.h index b629c970..bed1f0a6 100644 --- a/runtime/include/lib.h +++ b/runtime/include/lib.h @@ -14,7 +14,7 @@ #include "value_wrapper.h" -#define panic() assert(false) +#define PANIC() assert(false) struct CoroBase; struct CoroutineStatus; @@ -26,7 +26,7 @@ extern boost::context::fiber_context sched_ctx; extern std::optional coroutine_status; -struct CoroutineStatus{ +struct CoroutineStatus { std::string_view name; bool has_started; }; diff --git a/runtime/include/lincheck.h b/runtime/include/lincheck.h index 178fd3d5..195eee4d 100644 --- a/runtime/include/lincheck.h +++ b/runtime/include/lincheck.h @@ -32,7 +32,7 @@ struct Invoke { std::reference_wrapper task; }; -typedef std::variant HistoryEvent; +using HistoryEvent = std::variant; // ModelChecker is the general checker interface which is implemented by // different checkers, each of which checks its own consistency model @@ -45,18 +45,18 @@ using MethodName = std::string; // get_inv_res_mapping returns map (invoke_index -> corresponding // response_index) -std::map get_inv_res_mapping( +std::map GetInvResMapping( const std::vector& history); -std::map get_inv_res_full_mapping( +std::map GetInvResFullMapping( const std::vector& history); -std::map get_followup_res_request_inv_mapping( +std::map GetFollowupResRequestInvMapping( const std::vector& history); // fix_history deletes invokes that don't have corresponding responses, // this is allowed by the definition of the linearizability -std::vector> fix_history( +std::vector> FixHistory( const std::vector>& history); template // LinearSpecificationObject contains previous states stack std::vector states_stack; - std::map inv_res = get_inv_res_mapping(history); + std::map inv_res = GetInvResMapping(history); std::vector linearized(history.size(), false); size_t linearized_entries_count = 0; std::unordered_set< @@ -167,7 +167,8 @@ bool LinearizabilityChecker< bool was_checked = false; LinearSpecificationObject data_structure_state_copy = data_structure_state; - ValueWrapper res = method(&data_structure_state_copy, inv.GetTask()->GetArgs()); + ValueWrapper res = + method(&data_structure_state_copy, inv.GetTask()->GetArgs()); // If invoke doesn't have a response we can't check the response bool doesnt_have_response = diff --git a/runtime/include/lincheck_recursive.h b/runtime/include/lincheck_recursive.h index e2b24d28..1fd7d8ce 100644 --- a/runtime/include/lincheck_recursive.h +++ b/runtime/include/lincheck_recursive.h @@ -54,7 +54,7 @@ bool LinearizabilityCheckerRecursive< if (history.empty()) { return true; } - std::map inv_res = get_inv_res_mapping(history); + std::map inv_res = GetInvResMapping(history); std::function&, std::vector&, LinearSpecificationObject)> diff --git a/runtime/include/logger.h b/runtime/include/logger.h index 2141dc29..6d11d429 100644 --- a/runtime/include/logger.h +++ b/runtime/include/logger.h @@ -2,9 +2,9 @@ #include #ifdef DEBUG -#define debug(...) fprintf(__VA_ARGS__) +#define DEBUG(...) fprintf(__VA_ARGS__) #else -#define debug(...) +#define DEBUG(...) #endif struct Logger { @@ -18,9 +18,9 @@ struct Logger { return *this; } - void flush(); + void Flush(); }; -void logger_init(bool verbose); +void LoggerInit(bool verbose); -Logger& log(); +Logger& Log(); diff --git a/runtime/include/minimization.h b/runtime/include/minimization.h index 45039ce4..d382b5f7 100644 --- a/runtime/include/minimization.h +++ b/runtime/include/minimization.h @@ -69,7 +69,7 @@ struct GreedyRoundMinimizor : public RoundMinimizor { */ struct SameInterleavingMinimizor : public GreedyRoundMinimizor { protected: - virtual Scheduler::Result OnTasksRemoved( + Scheduler::Result OnTasksRemoved( SchedulerWithReplay& sched, const Scheduler::BothHistories& nonlinear_history, const std::unordered_set& task_ids) const override; @@ -87,10 +87,10 @@ struct SameInterleavingMinimizor : public GreedyRoundMinimizor { */ struct StrategyExplorationMinimizor : public GreedyRoundMinimizor { StrategyExplorationMinimizor() = delete; - explicit StrategyExplorationMinimizor(int runs_); + explicit StrategyExplorationMinimizor(int runs); protected: - virtual Scheduler::Result OnTasksRemoved( + Scheduler::Result OnTasksRemoved( SchedulerWithReplay& sched, const Scheduler::BothHistories& nonlinear_history, const std::unordered_set& task_ids) const override; diff --git a/runtime/include/pct_strategy.h b/runtime/include/pct_strategy.h index dd3d9852..047852c2 100644 --- a/runtime/include/pct_strategy.h +++ b/runtime/include/pct_strategy.h @@ -54,8 +54,8 @@ struct PctStrategy : public BaseStrategyWithThreads { // Have to ignore waiting threads, so can't do it faster than O(n) for (size_t i = 0; i < threads.size(); ++i) { // Ignore waiting tasks - if (!threads[i].empty() && - (threads[i].back()->IsParked() || threads[i].back()->IsBlocked())) { + if (!threads[i].Empty() && + (threads[i].Back()->IsParked() || threads[i].Back()->IsBlocked())) { // dual waiting if request finished, but follow up isn't // skip dual tasks that already have finished the request // section(follow-up will be executed in another task, so we can't @@ -80,8 +80,8 @@ struct PctStrategy : public BaseStrategyWithThreads { } } - if (threads[index_of_max].empty() || - threads[index_of_max].back()->IsReturned()) { + if (threads[index_of_max].Empty() || + threads[index_of_max].Back()->IsReturned()) { auto constructor = this->constructors.at(this->constructors_distribution(rng)); if (forbid_all_same) { @@ -100,12 +100,12 @@ struct PctStrategy : public BaseStrategyWithThreads { } } - threads[index_of_max].emplace_back( + threads[index_of_max].EmplaceBack( constructor.Build(&this->state, index_of_max, this->new_task_id++)); - return {threads[index_of_max].back(), true, index_of_max}; + return {threads[index_of_max].Back(), true, index_of_max}; } - return {threads[index_of_max].back(), false, index_of_max}; + return {threads[index_of_max].Back(), false, index_of_max}; } TaskWithMetaData NextSchedule() override { @@ -118,7 +118,7 @@ struct PctStrategy : public BaseStrategyWithThreads { for (size_t i = 0; i < threads.size(); ++i) { int task_index = this->GetNextTaskInThread(i); // Ignore waiting tasks - if (task_index == threads[i].size() || + if (task_index == threads[i].Size() || threads[i][task_index]->IsParked()) { // dual waiting if request finished, but follow up isn't // skip dual tasks that already have finished the request @@ -150,17 +150,17 @@ struct PctStrategy : public BaseStrategyWithThreads { void StartNextRound() override { this->new_task_id = 0; - // log() << "depth: " << current_depth << "\n"; + // Log() << "depth: " << current_depth << "\n"; // Reconstruct target as we start from the beginning. this->TerminateTasks(); for (auto& thread : this->threads) { // We don't have to keep references alive - while (thread.size() > 0) { - thread.pop_back(); + while (thread.Size() > 0) { + thread.PopBack(); } thread = StableVector(); } - //this->state.Reset(); + // this->state.Reset(); UpdateStatistics(); } @@ -185,7 +185,7 @@ struct PctStrategy : public BaseStrategyWithThreads { // current_depth have been increased size_t new_k = std::reduce(k_statistics.begin(), k_statistics.end()) / k_statistics.size(); - log() << "k: " << new_k << "\n"; + Log() << "k: " << new_k << "\n"; PrepareForDepth(current_depth, new_k); } @@ -194,11 +194,11 @@ struct PctStrategy : public BaseStrategyWithThreads { for (size_t i = 0; i < this->threads.size(); ++i) { auto& thread = this->threads[i]; - if (thread.empty() || i == except_thread) { + if (thread.Empty() || i == except_thread) { continue; } - auto& task = thread.back(); + auto& task = thread.Back(); names.insert(std::string{task->GetName()}); } diff --git a/runtime/include/pick_strategy.h b/runtime/include/pick_strategy.h index 71530642..33089566 100644 --- a/runtime/include/pick_strategy.h +++ b/runtime/include/pick_strategy.h @@ -34,11 +34,11 @@ struct PickStrategy : public BaseStrategyWithThreads { TaskWithMetaData Next() override { auto& threads = this->threads; auto current_thread = Pick(); - debug(stderr, "Picked thread: %zu\n", current_thread); + DEBUG(stderr, "Picked thread: %zu\n", current_thread); // it's the first task if the queue is empty - if (threads[current_thread].empty() || - threads[current_thread].back()->IsReturned()) { + if (threads[current_thread].Empty() || + threads[current_thread].Back()->IsReturned()) { // a task has finished or the queue is empty, so we add a new task std::shuffle(this->constructors.begin(), this->constructors.end(), rng); size_t verified_constructor = -1; @@ -54,15 +54,15 @@ struct PickStrategy : public BaseStrategyWithThreads { if (verified_constructor == -1) { assert(false && "Oops, possible deadlock or incorrect verifier\n"); } - threads[current_thread].emplace_back( + threads[current_thread].EmplaceBack( this->constructors[verified_constructor].Build( &this->state, current_thread, this->new_task_id++)); - TaskWithMetaData task{threads[current_thread].back(), true, + TaskWithMetaData task{threads[current_thread].Back(), true, current_thread}; return task; } - return {threads[current_thread].back(), false, current_thread}; + return {threads[current_thread].Back(), false, current_thread}; } TaskWithMetaData NextSchedule() override { @@ -82,13 +82,13 @@ struct PickStrategy : public BaseStrategyWithThreads { this->TerminateTasks(); for (auto& thread : this->threads) { // We don't have to keep references alive - while (thread.size() > 0) { - thread.pop_back(); + while (thread.Size() > 0) { + thread.PopBack(); } } // Reinitial target as we start from the beginning. - //this->state.Reset(); + // this->state.Reset(); } ~PickStrategy() { this->TerminateTasks(); } diff --git a/runtime/include/random_strategy.h b/runtime/include/random_strategy.h index 3765d785..7b90eee6 100644 --- a/runtime/include/random_strategy.h +++ b/runtime/include/random_strategy.h @@ -21,8 +21,8 @@ struct RandomStrategy : PickStrategy { pick_weights.clear(); auto &threads = PickStrategy::threads; for (size_t i = 0; i < threads.size(); ++i) { - if (!threads[i].empty() && - (threads[i].back()->IsParked() || threads[i].back()->IsBlocked())) { + if (!threads[i].Empty() && + (threads[i].Back()->IsParked() || threads[i].Back()->IsBlocked())) { continue; } pick_weights.push_back(weights[i]); @@ -34,8 +34,8 @@ struct RandomStrategy : PickStrategy { std::discrete_distribution<>(pick_weights.begin(), pick_weights.end()); auto num = thread_distribution(PickStrategy::rng); for (size_t i = 0; i < threads.size(); ++i) { - if (!threads[i].empty() && - (threads[i].back()->IsParked() || threads[i].back()->IsBlocked())) { + if (!threads[i].Empty() && + (threads[i].Back()->IsParked() || threads[i].Back()->IsBlocked())) { continue; } if (num == 0) { @@ -52,7 +52,7 @@ struct RandomStrategy : PickStrategy { for (size_t i = 0; i < threads.size(); ++i) { int task_index = this->GetNextTaskInThread(i); - if (task_index == threads[i].size() || + if (task_index == threads[i].Size() || threads[i][task_index]->IsParked()) { continue; } @@ -66,7 +66,7 @@ struct RandomStrategy : PickStrategy { auto num = thread_distribution(this->rng); for (size_t i = 0; i < threads.size(); ++i) { int task_index = this->GetNextTaskInThread(i); - if (task_index == threads[i].size() || + if (task_index == threads[i].Size() || threads[i][task_index]->IsParked()) { continue; } diff --git a/runtime/include/round_robin_strategy.h b/runtime/include/round_robin_strategy.h index b8ae99a1..98f14cbc 100644 --- a/runtime/include/round_robin_strategy.h +++ b/runtime/include/round_robin_strategy.h @@ -16,8 +16,8 @@ struct RoundRobinStrategy : PickStrategy { auto &threads = PickStrategy::threads; for (size_t attempt = 0; attempt < threads.size(); ++attempt) { auto cur = (next_task++) % threads.size(); - if (!threads[cur].empty() && (threads[cur].back()->IsParked() || - threads[cur].back()->IsBlocked())) { + if (!threads[cur].Empty() && (threads[cur].Back()->IsParked() || + threads[cur].Back()->IsBlocked())) { continue; } return cur; @@ -31,7 +31,7 @@ struct RoundRobinStrategy : PickStrategy { auto cur = (next_task++) % threads.size(); int task_index = this->GetNextTaskInThread(cur); - if (task_index == threads[cur].size() || + if (task_index == threads[cur].Size() || threads[cur][task_index]->IsParked()) { continue; } diff --git a/runtime/include/scheduler.h b/runtime/include/scheduler.h index a6c22e2e..0f1b4d53 100644 --- a/runtime/include/scheduler.h +++ b/runtime/include/scheduler.h @@ -124,7 +124,7 @@ struct BaseStrategyWithThreads : public Strategy { // TODO: can this be optimized? int thread_id = 0; for (auto& thread : threads) { - size_t tasks = thread.size(); + size_t tasks = thread.Size(); for (size_t i = 0; i < tasks; ++i) { Task& task = thread[i]; @@ -147,7 +147,7 @@ struct BaseStrategyWithThreads : public Strategy { TerminateTasks(); // state.Reset(); for (auto& thread : threads) { - size_t tasks_in_thread = thread.size(); + size_t tasks_in_thread = thread.Size(); for (size_t i = 0; i < tasks_in_thread; ++i) { if (!IsTaskRemoved(thread[i]->GetId())) { thread[i] = thread[i]->Restart(&state); @@ -159,7 +159,7 @@ struct BaseStrategyWithThreads : public Strategy { int GetValidTasksCount() const override { int non_removed_tasks = 0; for (auto& thread : threads) { - for (size_t i = 0; i < thread.size(); ++i) { + for (size_t i = 0; i < thread.Size(); ++i) { auto& task = thread[i]; if (!IsTaskRemoved(task->GetId())) { non_removed_tasks++; @@ -172,7 +172,7 @@ struct BaseStrategyWithThreads : public Strategy { int GetTotalTasksCount() const override { int total_tasks = 0; for (auto& thread : threads) { - total_tasks += thread.size(); + total_tasks += thread.Size(); } return total_tasks; } @@ -207,20 +207,20 @@ struct BaseStrategyWithThreads : public Strategy { auto& task_index = task_indexes[thread_index]; // find first non-finished task in the thread - while (task_index < thread.size() && thread[task_index]->IsReturned()) { + while (task_index < thread.Size() && thread[task_index]->IsReturned()) { task_index++; } - if (task_index < thread.size()) { + if (task_index < thread.Size()) { auto& task = thread[task_index]; // if task is blocked and it is the last one, then just increment the // task index if (task->IsBlocked()) { - assert(task_index == thread.size() - 1 && + assert(task_index == thread.Size() - 1 && "Trying to terminate blocked task, which is not last in the " "thread."); - if (task_index == thread.size() - 1) { + if (task_index == thread.Size() - 1) { task_index++; } } else { @@ -240,7 +240,7 @@ struct BaseStrategyWithThreads : public Strategy { auto& thread = threads[thread_index]; int task_index = round_schedule[thread_index]; - while (task_index < static_cast(thread.size()) && + while (task_index < static_cast(thread.Size()) && (task_index == -1 || thread[task_index].get()->IsReturned() || IsTaskRemoved(thread[task_index].get()->GetId()))) { task_index++; @@ -285,30 +285,30 @@ struct StrategyScheduler : public SchedulerWithReplay { // Resume operation on the corresponding task Scheduler::Result Run() override { for (size_t i = 0; i < max_rounds; ++i) { - log() << "run round: " << i << "\n"; - debug(stderr, "run round: %d\n", i); + Log() << "run round: " << i << "\n"; + DEBUG(stderr, "run round: %d\n", i); auto histories = RunRound(); if (histories.has_value()) { auto& [full_history, sequential_history] = histories.value(); if (should_minimize_history) { - log() << "Full nonlinear scenario: \n"; - pretty_printer.PrettyPrint(sequential_history, log()); + Log() << "Full nonlinear scenario: \n"; + pretty_printer.PrettyPrint(sequential_history, Log()); - log() << "Minimizing same interleaving...\n"; + Log() << "Minimizing same interleaving...\n"; Minimize(histories.value(), SameInterleavingMinimizor()); - log() << "Minimized to:\n"; - pretty_printer.PrettyPrint(sequential_history, log()); + Log() << "Minimized to:\n"; + pretty_printer.PrettyPrint(sequential_history, Log()); - log() << "Minimizing with rescheduling (exploration runs: " + Log() << "Minimizing with rescheduling (exploration runs: " << exploration_runs << ")...\n"; Minimize(histories.value(), StrategyExplorationMinimizor(exploration_runs)); - log() << "Minimized to:\n"; - pretty_printer.PrettyPrint(sequential_history, log()); + Log() << "Minimized to:\n"; + pretty_printer.PrettyPrint(sequential_history, Log()); - log() << "Minimizing with smart minimizor (exploration runs: " + Log() << "Minimizing with smart minimizor (exploration runs: " << exploration_runs << ", minimization runs: " << minimization_runs << ")...\n"; Minimize(histories.value(), @@ -318,8 +318,8 @@ struct StrategyScheduler : public SchedulerWithReplay { return histories; } - log() << "===============================================\n\n"; - log().flush(); + Log() << "===============================================\n\n"; + Log().Flush(); strategy.StartNextRound(); } @@ -335,7 +335,7 @@ struct StrategyScheduler : public SchedulerWithReplay { FullHistory full_history; for (size_t finished_tasks = 0; finished_tasks < max_tasks;) { - debug(stderr, "Tasks finished: %d\n", finished_tasks); + DEBUG(stderr, "Tasks finished: %d\n", finished_tasks); auto t = strategy.Next(); auto& [next_task, is_new, thread_id] = t; @@ -356,7 +356,7 @@ struct StrategyScheduler : public SchedulerWithReplay { } } - pretty_printer.PrettyPrint(sequential_history, log()); + pretty_printer.PrettyPrint(sequential_history, Log()); if (!checker.Check(sequential_history)) { return std::make_pair(full_history, sequential_history); @@ -368,7 +368,7 @@ struct StrategyScheduler : public SchedulerWithReplay { // Runs different interleavings of the current round Result ExploreRound(int runs) override { for (int i = 0; i < runs; ++i) { - // log() << "Run " << i + 1 << "/" << runs << "\n"; + // Log() << "Run " << i + 1 << "/" << runs << "\n"; strategy.ResetCurrentRound(); SeqHistory sequential_history; FullHistory full_history; @@ -393,8 +393,8 @@ struct StrategyScheduler : public SchedulerWithReplay { } if (!checker.Check(sequential_history)) { - // log() << "New nonlinearized scenario:\n"; - // pretty_printer.PrettyPrint(sequential_history, log()); + // Log() << "New nonlinearized scenario:\n"; + // pretty_printer.PrettyPrint(sequential_history,Log()); return std::make_pair(full_history, sequential_history); } } @@ -453,7 +453,7 @@ struct StrategyScheduler : public SchedulerWithReplay { } } - // pretty_printer.PrettyPrint(sequential_history, log()); + // pretty_printer.PrettyPrint(sequential_history,Log()); if (!checker.Check(sequential_history)) { return std::make_pair(full_history, sequential_history); @@ -498,7 +498,7 @@ struct TLAScheduler : Scheduler { max_depth(max_depth), cancel(cancel_func) { for (size_t i = 0; i < threads_count; ++i) { - threads.emplace_back(Thread{ + threads.EmplaceBack(Thread{ .id = i, .tasks = StableVector{}, }); @@ -510,7 +510,7 @@ struct TLAScheduler : Scheduler { return res; } - ~TLAScheduler() { TerminateTasks(); } + ~TLAScheduler() override { TerminateTasks(); } private: struct Thread { @@ -543,8 +543,8 @@ struct TLAScheduler : Scheduler { // cancel() func takes care for graceful shutdown void TerminateTasks() { cancel(); - for (size_t i = 0; i < threads.size(); ++i) { - for (size_t j = 0; j < threads[i].tasks.size(); ++j) { + for (size_t i = 0; i < threads.Size(); ++i) { + for (size_t j = 0; j < threads[i].tasks.Size(); ++j) { auto& task = threads[i].tasks[j]; if (!task->IsReturned()) { task->Terminate(); @@ -581,16 +581,17 @@ struct TLAScheduler : Scheduler { assert(coroutine_status->has_started); full_history.emplace_back(thread_id, task); } - //To prevent cases like this - // +--------+--------+ - // | T1 | T2 | - // +--------+--------+ - // | | Recv | - // | Send | | - // | | >read | - // | >flush | | - // +--------+--------+ - verifier.UpdateState(coroutine_status->name, thread_id, coroutine_status->has_started); + // To prevent cases like this + // +--------+--------+ + // | T1 | T2 | + // +--------+--------+ + // | | Recv | + // | Send | | + // | | >read | + // | >flush | | + // +--------+--------+ + verifier.UpdateState(coroutine_status->name, thread_id, + coroutine_status->has_started); full_history.emplace_back(thread_id, coroutine_status.value()); coroutine_status.reset(); } else { @@ -617,7 +618,7 @@ struct TLAScheduler : Scheduler { return {false, {}}; } } - auto& task = thread.tasks.back(); + auto& task = thread.tasks.Back(); frame.task = &task; thread_id_history.push_back(thread_id); @@ -644,10 +645,10 @@ struct TLAScheduler : Scheduler { return {is_over, res}; } } else { - log() << "run round: " << finished_rounds << "\n"; - pretty_printer.PrettyPrint(full_history, log()); - log() << "===============================================\n\n"; - log().flush(); + Log() << "run round: " << finished_rounds << "\n"; + pretty_printer.PrettyPrint(full_history, Log()); + Log() << "===============================================\n\n"; + Log().Flush(); // Stop, check if the the generated history is linearizable. ++finished_rounds; if (!checker.Check(sequential_history)) { @@ -694,21 +695,21 @@ struct TLAScheduler : Scheduler { std::tuple RunStep(size_t step, size_t switches) { // Push frame to the stack. - frames.emplace_back(Frame{}); - auto& frame = frames.back(); + frames.EmplaceBack(Frame{}); + auto& frame = frames.Back(); bool all_parked = true; // Pick next task. - for (size_t i = 0; i < threads.size(); ++i) { + for (size_t i = 0; i < threads.Size(); ++i) { auto& thread = threads[i]; auto& tasks = thread.tasks; - if (!tasks.empty() && !tasks.back()->IsReturned()) { - if (tasks.back()->IsParked()) { + if (!tasks.Empty() && !tasks.Back()->IsReturned()) { + if (tasks.Back()->IsParked()) { continue; } all_parked = false; if (!verifier.Verify(CreatedTaskMetaData{ - std::string{tasks.back()->GetName()}, false, i})) { + std::string{tasks.Back()->GetName()}, false, i})) { continue; } // Task exists. @@ -726,21 +727,21 @@ struct TLAScheduler : Scheduler { all_parked = false; // Choose constructor to create task. bool stop = started_tasks == max_tasks; - if (!stop && threads[i].tasks.size() < max_depth) { + if (!stop && threads[i].tasks.Size() < max_depth) { for (auto cons : constructors) { if (!verifier.Verify(CreatedTaskMetaData{cons.GetName(), true, i})) { continue; } frame.is_new = true; - auto size_before = tasks.size(); - tasks.emplace_back(cons.Build(&state, i, -1/* TODO: fix task id for tla, because it is Scheduler and not Strategy class for some reason */)); + auto size_before = tasks.Size(); + tasks.EmplaceBack(cons.Build(&state, i, -1/* TODO: fix task id for tla, because it is Scheduler and not Strategy class for some reason */)); started_tasks++; auto [is_over, res] = ResumeTask(frame, step, switches, thread, true); if (is_over || res.has_value()) { return {is_over, res}; } - tasks.pop_back(); - auto size_after = thread.tasks.size(); + tasks.PopBack(); + auto size_after = thread.tasks.Size(); assert(size_before == size_after); // As we can't return to the past in coroutine, we need to replay all // tasks from the beginning. @@ -750,7 +751,7 @@ struct TLAScheduler : Scheduler { } assert(!all_parked && "deadlock"); - frames.pop_back(); + frames.PopBack(); return {false, {}}; } diff --git a/runtime/include/stable_vector.h b/runtime/include/stable_vector.h index 6067fd8f..960579d6 100644 --- a/runtime/include/stable_vector.h +++ b/runtime/include/stable_vector.h @@ -32,7 +32,7 @@ struct StableVector { ~StableVector() { for (size_t i = 0; i < entities.size(); ++i) { if (entities[i]) { - for (size_t j = 0; j < (1ULL << i) && j + (1ULL << i) < size() + 1; + for (size_t j = 0; j < (1ULL << i) && j + (1ULL << i) < Size() + 1; ++j) { std::launder(reinterpret_cast(entities[i][j]))->~T(); } @@ -44,15 +44,15 @@ struct StableVector { } } - using type_t = std::byte[sizeof(T)]; + using TypeT = std::byte[sizeof(T)]; //NOLINT(modernize-avoid-c-arrays) template requires std::constructible_from - T &emplace_back(Args &&...args) { + T &EmplaceBack(Args &&...args) { const size_t index = 63 - __builtin_clzll(total_size + 1); if (((total_size + 1) & total_size) == 0 && !entities[index]) { entities[index] = ::new (static_cast(alignof(T))) - type_t[1ULL << index]; + TypeT[1ULL << index]; } const size_t internal_index = (total_size + 1) ^ (1ULL << index); T *t = @@ -61,7 +61,7 @@ struct StableVector { return *t; } - void pop_back() noexcept { + void PopBack() noexcept { const size_t index = 63 - __builtin_clzll(total_size); if (((total_size - 1) & total_size) == 0 && entities[index + 1]) { ::operator delete[](std::exchange(entities[index + 1], nullptr), @@ -86,28 +86,28 @@ struct StableVector { reinterpret_cast(entities[index][internal_index])); } - void resize(size_t new_size) { + void Resize(size_t new_size) { while (new_size > total_size) { - emplace_back(); + EmplaceBack(); } while (new_size < total_size) { - pop_back(); + PopBack(); } } - T &front() { return this->operator[](0); } + T &Front() { return this->operator[](0); } - const T &front() const { return this->operator[](0); } + const T &Front() const { return this->operator[](0); } - T &back() { return this->operator[](total_size - 1); } + T &Back() { return this->operator[](total_size - 1); } - const T &back() const { return this->operator[](total_size - 1); } + const T &Back() const { return this->operator[](total_size - 1); } - [[nodiscard]] size_t size() const { return total_size; } + [[nodiscard]] size_t Size() const { return total_size; } - [[nodiscard]] bool empty() const { return size() == 0; } + [[nodiscard]] bool Empty() const { return Size() == 0; } private: - std::array entities{}; + std::array entities{}; size_t total_size = 0; }; diff --git a/runtime/include/strategy_verifier.h b/runtime/include/strategy_verifier.h index edba95ea..399a745b 100644 --- a/runtime/include/strategy_verifier.h +++ b/runtime/include/strategy_verifier.h @@ -7,5 +7,5 @@ struct DefaultStrategyVerifier { inline void OnFinished(TaskWithMetaData task) {} inline void Reset() {} - inline void UpdateState(std::string_view, int, bool){} + inline void UpdateState(std::string_view, int, bool) {} }; diff --git a/runtime/include/syscall_trap.h b/runtime/include/syscall_trap.h index 196e5f18..2fe42755 100644 --- a/runtime/include/syscall_trap.h +++ b/runtime/include/syscall_trap.h @@ -1,6 +1,6 @@ #pragma once -extern bool __trap_syscall; +extern bool __trap_syscall; // NOLINT(readability-identifier-naming) namespace ltest { diff --git a/runtime/include/value_wrapper.h b/runtime/include/value_wrapper.h index 8bda0791..434ff0f4 100644 --- a/runtime/include/value_wrapper.h +++ b/runtime/include/value_wrapper.h @@ -28,8 +28,8 @@ class ValueWrapper { bool operator==(const ValueWrapper& other) const { return compare(*this, other); } - //using std::to_string - friend std::string to_string(const ValueWrapper& wrapper) { // NOLINT + // using std::to_string + friend std::string to_string(const ValueWrapper& wrapper) { // NOLINT return wrapper.to_str(wrapper); } bool HasValue() const { return value.has_value(); } diff --git a/runtime/include/verifying.h b/runtime/include/verifying.h index c4391dc4..800fbfbf 100644 --- a/runtime/include/verifying.h +++ b/runtime/include/verifying.h @@ -31,12 +31,12 @@ template , class OptionsOverride = NoOverride, class Canceler = DefaultCanceler> struct Spec { - using target_obj_t = TargetObj; - using linear_spec_t = LinearSpec; - using linear_spec_hash_t = LinearSpecHash; - using linear_spec_equals_t = LinearSpecEquals; - using options_override_t = OptionsOverride; - using cancel_t = Canceler; + using TargetObjT = TargetObj; + using LinearSpecT = LinearSpec; + using LinearSpecHashT = LinearSpecHash; + using LinearSpecEqualsT = LinearSpecEquals; + using OptionsOverrideT = OptionsOverride; + using CancelT = Canceler; }; struct Opts { @@ -73,7 +73,7 @@ void SetOpts(const DefaultOptions &def); Opts ParseOpts(); -std::vector split(const std::string &s, char delim); +std::vector Split(const std::string &s, char delim); template std::unique_ptr MakeStrategy(Opts &opts, std::vector l) { @@ -168,14 +168,14 @@ inline int TrapRun(std::unique_ptr &&scheduler, template int Run(int argc, char *argv[]) { - if constexpr (!std::is_same_v) { - SetOpts(Spec::options_override_t::GetOptions()); + SetOpts(Spec::OptionsOverrideT::GetOptions()); } gflags::ParseCommandLineFlags(&argc, &argv, true); Opts opts = ParseOpts(); - logger_init(opts.verbose); + LoggerInit(opts.verbose); std::cout << "verbose: " << std::boolalpha << opts.verbose << "\n"; std::cout << "threads = " << opts.threads << "\n"; std::cout << "tasks = " << opts.tasks << "\n"; @@ -190,16 +190,16 @@ int Run(int argc, char *argv[]) { PrettyPrinter pretty_printer{opts.threads}; - using lchecker_t = - LinearizabilityCheckerRecursive; - lchecker_t checker{Spec::linear_spec_t::GetMethods(), - typename Spec::linear_spec_t{}}; + using LcheckerT = + LinearizabilityCheckerRecursive; + LcheckerT checker{Spec::LinearSpecT::GetMethods(), + typename Spec::LinearSpecT{}}; - auto scheduler = MakeScheduler( + auto scheduler = MakeScheduler( checker, opts, std::move(task_builders), pretty_printer, - &Spec::cancel_t::Cancel); + &Spec::CancelT::Cancel); std::cout << "\n\n"; std::cout.flush(); return TrapRun(std::move(scheduler), pretty_printer); diff --git a/runtime/include/verifying_macro.h b/runtime/include/verifying_macro.h index 50b66401..aa65754b 100644 --- a/runtime/include/verifying_macro.h +++ b/runtime/include/verifying_macro.h @@ -14,46 +14,47 @@ extern std::vector task_builders; } // namespace ltest // Adds an attribute. -#define attr(attr) __attribute((__annotate__(#attr))) +#define ATTR(attr) __attribute((__annotate__(#attr))) // Tell that the function need to be converted to the coroutine. -#define non_atomic attr(ltest_nonatomic) +#define NON_ATOMIC ATTR(ltest_nonatomic) namespace ltest { template -std::string toString(const T &a); +std::string ToString(const T &a); template -std::string toString(const T &a) requires (std::is_integral_v){ +std::string ToString(const T &a) + requires(std::is_integral_v) +{ return std::to_string(a); } - template -auto toStringListHelper(const tuple_t &t, +auto ToStringListHelper(const tuple_t &t, std::index_sequence) noexcept { - return std::vector{ltest::toString(std::get(t))...}; + return std::vector{ltest::ToString(std::get(t))...}; } template -auto toStringList(const tuple_t &t) noexcept { - typedef typename std::remove_reference::type tuple_type; - constexpr auto s = std::tuple_size::value; +auto ToStringList(const tuple_t &t) noexcept { + using TupleType = typename std::remove_reference::type; + constexpr auto s = std::tuple_size::value; if constexpr (s == 0) { return std::vector{}; } - return toStringListHelper(t, std::make_index_sequence{}); + return ToStringListHelper(t, std::make_index_sequence{}); } template -auto toStringArgs(std::shared_ptr args) { +auto ToStringArgs(std::shared_ptr args) { auto real_args = reinterpret_cast *>(args.get()); - return toStringList(*real_args); + return ToStringList(*real_args); } template -struct TargetMethod{ +struct TargetMethod { using Method = std::function; TargetMethod(std::string_view method_name, std::function(size_t)> gen, Method method) { @@ -62,7 +63,7 @@ struct TargetMethod{ void *this_ptr, size_t thread_num, int task_id) -> Task { auto args = std::shared_ptr(new std::tuple(gen(thread_num))); auto coro = Coro::New(method, this_ptr, args, - <est::toStringArgs, + <est::ToStringArgs, method_name, task_id); if (ltest::generators::generated_token) { coro->SetToken(ltest::generators::generated_token); @@ -75,7 +76,6 @@ struct TargetMethod{ } }; - template struct TargetMethod { using Method = std::function; @@ -86,11 +86,12 @@ struct TargetMethod { method = std::move(method)]( void *this_ptr, size_t thread_num, int task_id) -> Task { auto wrapper = [f = std::move(method)](void *this_ptr, Args &&...args) { - f(reinterpret_cast(this_ptr), std::forward(args)...); - return void_v; - }; auto args = std::shared_ptr(new std::tuple(gen(thread_num))); + f(reinterpret_cast(this_ptr), std::forward(args)...); + return void_v; + }; + auto args = std::shared_ptr(new std::tuple(gen(thread_num))); auto coro = Coro::New(wrapper, this_ptr, args, - <est::toStringArgs, + <est::ToStringArgs, method_name, task_id); if (ltest::generators::generated_token) { coro->SetToken(ltest::generators::generated_token); @@ -105,9 +106,9 @@ struct TargetMethod { } // namespace ltest -#define declare_task_name(symbol) const char *symbol##_task_name = #symbol +#define DECLARE_TASK_METHOD(symbol) const char *symbol##_task_name = #symbol -#define target_method(gen, ret, cls, symbol, ...) \ - declare_task_name(symbol); \ +#define TARGET_METHOD(gen, ret, cls, symbol, ...) \ + DECLARE_TASK_METHOD(symbol); \ ltest::TargetMethod \ symbol##_ltest_method_cls{symbol##_task_name, gen, &cls::symbol}; diff --git a/runtime/lin_check.cpp b/runtime/lin_check.cpp index ae20eaf3..8f6ae390 100644 --- a/runtime/lin_check.cpp +++ b/runtime/lin_check.cpp @@ -5,7 +5,7 @@ // get_inv_res_mapping returns map (invoke_index -> corresponding // response_index) -std::map get_inv_res_mapping( +std::map GetInvResMapping( const std::vector> &history) { std::map inv_res; // inv -> corresponding response std::map uids; // uid -> res diff --git a/runtime/logger.cpp b/runtime/logger.cpp index 738ee70e..38c8bbcd 100644 --- a/runtime/logger.cpp +++ b/runtime/logger.cpp @@ -4,12 +4,12 @@ Logger l{}; -void logger_init(bool verbose) { l.verbose = verbose; } +void LoggerInit(bool verbose) { l.verbose = verbose; } -void Logger::flush() { +void Logger::Flush() { if (verbose) { std::cout.flush(); } } -Logger& log() { return l; } +Logger& Log() { return l; } diff --git a/runtime/minimization.cpp b/runtime/minimization.cpp index b42a5479..79a53d46 100644 --- a/runtime/minimization.cpp +++ b/runtime/minimization.cpp @@ -33,7 +33,7 @@ void GreedyRoundMinimizor::Minimize( for (auto& task : tasks) { if (strategy.IsTaskRemoved(task.get()->GetId())) continue; - // log() << "Try to remove task with id: " << task.get()->GetId() << "\n"; + // Log() << "Try to remove task with id: " << task.get()->GetId() << "\n"; auto new_histories = OnTasksRemoved(sched, nonlinear_history, {task.get()->GetId()}); @@ -55,9 +55,9 @@ void GreedyRoundMinimizor::Minimize( int task_j_id = task_j->GetId(); if (strategy.IsTaskRemoved(task_j_id)) continue; - // log() << "Try to remove tasks with ids: " << task_i.get()->GetId() << " - // and " - // << task_j.get()->GetId() << "\n"; + // Log() << "Try to remove tasks with ids: " << task_i.get()->GetId() << " + // and " + // << task_j.get()->GetId() << "\n"; auto new_histories = OnTasksRemoved(sched, nonlinear_history, {task_i_id, task_j_id}); @@ -94,8 +94,8 @@ Scheduler::Result SameInterleavingMinimizor::OnTasksRemoved( } // strategy exploration -StrategyExplorationMinimizor::StrategyExplorationMinimizor(int runs_) - : runs(runs_) {} +StrategyExplorationMinimizor::StrategyExplorationMinimizor(int runs) + : runs(runs) {} Scheduler::Result StrategyExplorationMinimizor::OnTasksRemoved( SchedulerWithReplay& sched, diff --git a/runtime/minimization_smart.cpp b/runtime/minimization_smart.cpp index bc047f00..d66df8ed 100644 --- a/runtime/minimization_smart.cpp +++ b/runtime/minimization_smart.cpp @@ -151,7 +151,7 @@ void SmartMinimizor::RemoveInvalidTasks( const auto& thread = tasks[thread_id]; bool thread_exists = valid_threads.contains(thread_id); - for (int i = 0; i < thread.size(); ++i) { + for (int i = 0; i < thread.Size(); ++i) { if (thread_exists && valid_threads.at(thread_id).contains(thread[i]->GetId())) { strategy.SetTaskRemoved(thread[i]->GetId(), false); @@ -205,7 +205,7 @@ SmartMinimizor::Solution::Solution(const Strategy& strategy, // save valid task ids per thread const auto& threads = strategy.GetTasks(); for (int i = 0; i < threads.size(); ++i) { - for (int j = 0; j < threads[i].size(); ++j) { + for (int j = 0; j < threads[i].Size(); ++j) { const auto& task = threads[i][j].get(); if (!strategy.IsTaskRemoved(task->GetId())) { diff --git a/runtime/verifying.cpp b/runtime/verifying.cpp index c71b9905..7c5df815 100644 --- a/runtime/verifying.cpp +++ b/runtime/verifying.cpp @@ -8,17 +8,17 @@ namespace ltest { template <> -std::string toString(const int &a) { +std::string ToString(const int &a) { return std::to_string(a); } template <> -std::string toString>( +std::string ToString>( const std::shared_ptr &token) { return "token"; } -std::string toLower(std::string str) { +std::string ToLower(std::string str) { std::transform(str.begin(), str.end(), str.begin(), [](unsigned char c) { return std::tolower(c); }); return str; @@ -74,7 +74,7 @@ DEFINE_int32(exploration_runs, 15, DEFINE_int32(minimization_runs, 15, "Number of minimization runs for smart minimizor"); DEFINE_int32(depth, 0, - "How many tasks can be executed on one thread(Only for TLA)"); + "How many tasks can be executed on one thread(Only for TLA)"); DEFINE_bool(verbose, false, "Verbosity"); DEFINE_bool( forbid_all_same, false, @@ -104,7 +104,8 @@ Opts ParseOpts() { opts.switches = FLAGS_switches; opts.rounds = FLAGS_rounds; opts.forbid_all_same = FLAGS_forbid_all_same; - opts.minimize = FLAGS_minimize; // NOTE(dartiukhov) minimization for scenarios with locks is not supported + opts.minimize = FLAGS_minimize; // NOTE(dartiukhov) minimization for + // scenarios with locks is not supported opts.exploration_runs = FLAGS_exploration_runs; opts.minimization_runs = FLAGS_minimization_runs; opts.verbose = FLAGS_verbose; diff --git a/scripts/run_tidy.sh b/scripts/run_tidy.sh new file mode 100755 index 00000000..6b88da4b --- /dev/null +++ b/scripts/run_tidy.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# need build directory with compile_commands.json +clang-tidy verifying/lib/* verifying/blocking/*.cpp verifying/targets/*.cpp verifying/specs/*.h \ + test/runtime/*.cpp runtime/include/*.h codegen/*.cpp \ +-p build/compile_commands.json --extra-arg=-std=c++20 \ No newline at end of file diff --git a/syscall_intercept/hook.cpp b/syscall_intercept/hook.cpp index 976b7a8b..8f626e5e 100644 --- a/syscall_intercept/hook.cpp +++ b/syscall_intercept/hook.cpp @@ -17,11 +17,11 @@ hook(long syscall_number, return 1; } if (syscall_number == SYS_sched_yield) { - debug(stderr, "caught sched_yield()\n"); + DEBUG(stderr, "caught sched_yield()\n"); CoroYield(); return 0; } else if (syscall_number == SYS_futex) { - debug(stderr, "caught futex(0x%lx, %ld, %ld)\n", (unsigned long)arg0, arg1, arg2); + DEBUG(stderr, "caught futex(0x%lx, %ld, %ld)\n", (unsigned long)arg0, arg1, arg2); if (arg1 == FUTEX_WAIT_PRIVATE) { this_coro->SetBlocked(arg0, arg2); } else if (arg1 == FUTEX_WAKE_PRIVATE) { diff --git a/test/runtime/lin_check_test.cpp b/test/runtime/lin_check_test.cpp index 3152628f..6d3983d6 100644 --- a/test/runtime/lin_check_test.cpp +++ b/test/runtime/lin_check_test.cpp @@ -42,7 +42,7 @@ std::shared_ptr CreateMockTask(std::string name, int ret_val, return static_pointer_cast(mock); } -namespace LinearizabilityCheckerTest { +namespace linearizability_checker_test { using ::testing::AnyNumber; using ::testing::Return; using ::testing::ReturnRefOfCopy; @@ -158,7 +158,7 @@ TEST(LinearizabilityCheckerCounterTest, ExtendedLinearizableHistory) { EXPECT_EQ(checker.Check(history), true); } -std::vector create_mocks(const std::vector& b_history) { +std::vector CreateMocks(const std::vector& b_history) { std::vector mocks; mocks.reserve(b_history.size()); size_t adds = 0; @@ -179,7 +179,7 @@ std::vector create_mocks(const std::vector& b_history) { return mocks; } -std::vector create_history(const std::vector& mocks) { +std::vector CreateHistory(const std::vector& mocks) { std::vector history; history.reserve(2 * mocks.size()); @@ -211,7 +211,7 @@ std::vector create_history(const std::vector& mocks) { return history; } -std::string draw_history(const std::vector& history) { +std::string DrawHistory(const std::vector& history) { std::map numeration; size_t i = 0; for (auto& event : history) { @@ -235,8 +235,8 @@ std::string draw_history(const std::vector& history) { Response response = std::get(event); history_string << "[" << numeration[response.GetTask()] << " res: " << response.GetTask()->GetName() - << " returned: " << to_string(response.GetTask()->GetRetVal()) - << "]\n"; + << " returned: " + << to_string(response.GetTask()->GetRetVal()) << "]\n"; } } @@ -260,11 +260,11 @@ void CheckersAreTheSame(const std::vector& b_history) { }, c); - auto mocks = create_mocks(b_history); - auto history = create_history(mocks); - EXPECT_EQ(fast.Check(history), slow.Check(history)) << draw_history(history); + auto mocks = CreateMocks(b_history); + auto history = CreateHistory(mocks); + EXPECT_EQ(fast.Check(history), slow.Check(history)) << DrawHistory(history); } FUZZ_TEST(LinearizabilityCheckerCounterTest, CheckersAreTheSame); -}; // namespace LinearizabilityCheckerTest \ No newline at end of file +}; // namespace linearizability_checker_test \ No newline at end of file diff --git a/test/runtime/stackfulltask_mock.h b/test/runtime/stackfulltask_mock.h index 32fd28a2..136198ea 100644 --- a/test/runtime/stackfulltask_mock.h +++ b/test/runtime/stackfulltask_mock.h @@ -18,5 +18,5 @@ class MockTask : public CoroBase { MOCK_METHOD(bool, IsSuspended, (), (const)); MOCK_METHOD(void, Terminate, (), ()); MOCK_METHOD(void, SetToken, (std::shared_ptr), ()); - virtual ~MockTask() { is_returned = true; } + ~MockTask() override { is_returned = true; } }; diff --git a/verifying/README.md b/verifying/README.md index 3fffb2a4..9044bdde 100644 --- a/verifying/README.md +++ b/verifying/README.md @@ -13,8 +13,8 @@ * Точка входа генерируется макросом `LTEST_ENTRYPOINT(spec)`. -Тестируемые методы должны быть реализованы с помощью макроса `target_method` (*эти макросы должны идти обязательно после `LTEST_ENTRYPOINT(spec)`*). -Все прочие методы и функции, которые не должны считаться атомарными, должны быть помечены с помощью `non_atomic`. +Тестируемые методы должны быть реализованы с помощью макроса `TARGET_METHOD` (*эти макросы должны идти обязательно после `LTEST_ENTRYPOINT(spec)`*). +Все прочие методы и функции, которые не должны считаться атомарными, должны быть помечены с помощью `NON_ATOMIC`. Для тестирования методов с возвращаемым типом `void` в GetMethods ключу необходимо возвращать `void_v`. diff --git a/verifying/blocking/folly_rwspinlock.cpp b/verifying/blocking/folly_rwspinlock.cpp index caece8f3..fde95d0a 100644 --- a/verifying/blocking/folly_rwspinlock.cpp +++ b/verifying/blocking/folly_rwspinlock.cpp @@ -20,9 +20,9 @@ class RWSpinLock { RWSpinLock& operator=(RWSpinLock const&) = delete; // Lockable Concept - non_atomic int lock() { + NON_ATOMIC int Lock() { uint_fast32_t count = 0; - while (!LIKELY(try_lock())) { + while (!LIKELY(TryLock())) { if (++count > 1000) { std::this_thread::yield(); } @@ -31,16 +31,16 @@ class RWSpinLock { } // Writer is responsible for clearing up both the UPGRADED and WRITER bits. - non_atomic int unlock() { + NON_ATOMIC int Unlock() { static_assert(READER > WRITER + UPGRADED, "wrong bits!"); bits_.fetch_and(~(WRITER | UPGRADED), std::memory_order_release); return 0; } // SharedLockable Concept - non_atomic int lock_shared() { + NON_ATOMIC int LockShared() { uint_fast32_t count = 0; - while (!LIKELY(try_lock_shared())) { + while (!LIKELY(TryLockShared())) { if (++count > 1000) { std::this_thread::yield(); } @@ -48,35 +48,35 @@ class RWSpinLock { return 0; } - non_atomic int unlock_shared() { + NON_ATOMIC int UnlockShared() { bits_.fetch_add(-READER, std::memory_order_release); return 0; } // Downgrade the lock from writer status to reader status. - void unlock_and_lock_shared() { + void UnlockAndLockShared() { bits_.fetch_add(READER, std::memory_order_acquire); - unlock(); + Unlock(); } // UpgradeLockable Concept - void lock_upgrade() { + void LockUpgrade() { uint_fast32_t count = 0; - while (!try_lock_upgrade()) { + while (!TryLockUpgrade()) { if (++count > 1000) { std::this_thread::yield(); } } } - void unlock_upgrade() { + void UnlockUpgrade() { bits_.fetch_add(-UPGRADED, std::memory_order_acq_rel); } // unlock upgrade and try to acquire write lock - void unlock_upgrade_and_lock() { + void UnlockUpgradeAndLock() { int64_t count = 0; - while (!try_unlock_upgrade_and_lock()) { + while (!TryUnlockUpgradeAndLock()) { if (++count > 1000) { std::this_thread::yield(); } @@ -84,12 +84,12 @@ class RWSpinLock { } // unlock upgrade and read lock atomically - void unlock_upgrade_and_lock_shared() { + void UnlockUpgradeAndLockShared() { bits_.fetch_add(READER - UPGRADED, std::memory_order_acq_rel); } // write unlock and upgrade lock atomically - void unlock_and_lock_upgrade() { + void UnlockAndLockUpgrade() { // need to do it in two steps here -- as the UPGRADED bit might be OR-ed at // the same time when other threads are trying do try_lock_upgrade(). bits_.fetch_or(UPGRADED, std::memory_order_acquire); @@ -97,7 +97,7 @@ class RWSpinLock { } // Attempt to acquire writer permission. Return false if we didn't get it. - bool try_lock() { + bool TryLock() { int32_t expect = 0; return bits_.compare_exchange_strong(expect, WRITER, std::memory_order_acq_rel); @@ -109,7 +109,7 @@ class RWSpinLock { // its intention to write and block any new readers while waiting // for existing readers to finish and release their read locks. This // helps avoid starving writers (promoted from upgraders). - bool try_lock_shared() { + bool TryLockShared() { // fetch_add is considerably (100%) faster than compare_exchange, // so here we are optimizing for the common (lock success) case. int32_t value = bits_.fetch_add(READER, std::memory_order_acquire); @@ -121,14 +121,14 @@ class RWSpinLock { } // try to unlock upgrade and write lock atomically - bool try_unlock_upgrade_and_lock() { + bool TryUnlockUpgradeAndLock() { int32_t expect = UPGRADED; return bits_.compare_exchange_strong(expect, WRITER, std::memory_order_acq_rel); } // try to acquire an upgradable lock. - bool try_lock_upgrade() { + bool TryLockUpgrade() { int32_t value = bits_.fetch_or(UPGRADED, std::memory_order_acquire); // Note: when failed, we cannot flip the UPGRADED bit back, @@ -139,7 +139,7 @@ class RWSpinLock { } // mainly for debugging purposes. - int32_t bits() const { return bits_.load(std::memory_order_acquire); } + int32_t Bits() const { return bits_.load(std::memory_order_acquire); } void Reset() { bits_.store(0); } @@ -148,14 +148,14 @@ class RWSpinLock { }; } // namespace folly -using spec_t = +using SpecT = ltest::Spec; -LTEST_ENTRYPOINT_CONSTRAINT(spec_t, SharedMutexVerifier); +LTEST_ENTRYPOINT_CONSTRAINT(SpecT, SharedMutexVerifier); -target_method(ltest::generators::genEmpty, int, folly::RWSpinLock, lock); -target_method(ltest::generators::genEmpty, int, folly::RWSpinLock, lock_shared); +TARGET_METHOD(ltest::generators::GenEmpty, int, folly::RWSpinLock, lock); +TARGET_METHOD(ltest::generators::GenEmpty, int, folly::RWSpinLock, LockShared); -target_method(ltest::generators::genEmpty, int, folly::RWSpinLock, unlock); -target_method(ltest::generators::genEmpty, int, folly::RWSpinLock, unlock_shared); \ No newline at end of file +TARGET_METHOD(ltest::generators::GenEmpty, int, folly::RWSpinLock, Unlock); +TARGET_METHOD(ltest::generators::GenEmpty, int, folly::RWSpinLock, unlock_shared); \ No newline at end of file diff --git a/verifying/blocking/mutexed_register.cpp b/verifying/blocking/mutexed_register.cpp index c9d38f44..b7c15cb8 100644 --- a/verifying/blocking/mutexed_register.cpp +++ b/verifying/blocking/mutexed_register.cpp @@ -4,14 +4,14 @@ #include "runtime/include/verifying.h" #include "verifying/specs/register.h" -typedef folly::detail::lock_base_unique lock_guard; +using lock_guard = folly::detail::lock_base_unique ; struct Register { - non_atomic void add() { + NON_ATOMIC void Add() { lock_guard lock{m_}; ++x_; } - non_atomic int get() { + NON_ATOMIC int Get() { lock_guard lock{m_}; return x_; } @@ -25,12 +25,12 @@ struct Register { std::mutex m_; }; -using spec_t = +using SpecT = ltest::Spec; -LTEST_ENTRYPOINT(spec_t); +LTEST_ENTRYPOINT(SpecT); -target_method(ltest::generators::genEmpty, void, Register, add); +TARGET_METHOD(ltest::generators::GenEmpty, void, Register, Add); -target_method(ltest::generators::genEmpty, int, Register, get); \ No newline at end of file +TARGET_METHOD(ltest::generators::GenEmpty, int, Register, Get); \ No newline at end of file diff --git a/verifying/blocking/nonlinear_mutex.cpp b/verifying/blocking/nonlinear_mutex.cpp index 2c8bedc8..f70e5871 100644 --- a/verifying/blocking/nonlinear_mutex.cpp +++ b/verifying/blocking/nonlinear_mutex.cpp @@ -28,7 +28,7 @@ class Mutex { } public: - non_atomic int Lock() { + NON_ATOMIC int Lock() { if (CompareExchange(0, 1) == 0) { return 0; } @@ -42,7 +42,7 @@ class Mutex { return 0; } - non_atomic int Unlock() { + NON_ATOMIC int Unlock() { if (locked_.fetch_sub(1) != 1) { locked_.store(0); FutexWake(Addr(locked_), 1); @@ -56,11 +56,11 @@ class Mutex { std::atomic_int32_t locked_{0}; }; -using spec_t = ltest::Spec; -LTEST_ENTRYPOINT_CONSTRAINT(spec_t, MutexVerifier); +LTEST_ENTRYPOINT_CONSTRAINT(SpecT, MutexVerifier); -target_method(ltest::generators::genEmpty, int, Mutex, Lock); +TARGET_METHOD(ltest::generators::GenEmpty, int, Mutex, Lock); -target_method(ltest::generators::genEmpty, int, Mutex, Unlock); \ No newline at end of file +TARGET_METHOD(ltest::generators::GenEmpty, int, Mutex, Unlock); \ No newline at end of file diff --git a/verifying/blocking/simple_mutex.cpp b/verifying/blocking/simple_mutex.cpp index 65629310..ca4f5583 100644 --- a/verifying/blocking/simple_mutex.cpp +++ b/verifying/blocking/simple_mutex.cpp @@ -29,10 +29,10 @@ class Mutex { } public: - non_atomic int Lock() { - debug(stderr, "Lock\n"); + NON_ATOMIC int Lock() { + DEBUG(stderr, "Lock\n"); if (CompareExchange(0, 1) == 0) { - debug(stderr, "Lock finished\n"); + DEBUG(stderr, "Lock finished\n"); return 0; } while (CompareExchange(0, 2) != 0) { @@ -42,17 +42,17 @@ class Mutex { } } } - debug(stderr, "Lock finished with %d\n", locked_.load()); + DEBUG(stderr, "Lock finished with %d\n", locked_.load()); return 0; } - non_atomic int Unlock() { - debug(stderr, "Unlock\n"); + NON_ATOMIC int Unlock() { + DEBUG(stderr, "Unlock\n"); if (locked_.fetch_sub(1) != 1) { locked_.store(0); FutexWake(Addr(locked_), 1); } - debug(stderr, "Unlock finished\n"); + DEBUG(stderr, "Unlock finished\n"); return 0; } @@ -62,11 +62,11 @@ class Mutex { std::atomic_int32_t locked_{0}; }; -using spec_t = ltest::Spec; +using SpecT = ltest::Spec; -LTEST_ENTRYPOINT_CONSTRAINT(spec_t, MutexVerifier); +LTEST_ENTRYPOINT_CONSTRAINT(SpecT, MutexVerifier); -target_method(ltest::generators::genEmpty, int, Mutex, Lock); +TARGET_METHOD(ltest::generators::GenEmpty, int, Mutex, Lock); -target_method(ltest::generators::genEmpty, int, Mutex, Unlock); \ No newline at end of file +TARGET_METHOD(ltest::generators::GenEmpty, int, Mutex, Unlock); \ No newline at end of file diff --git a/verifying/blocking/verifiers/mutex_verifier.h b/verifying/blocking/verifiers/mutex_verifier.h index cef4f2b4..54c1c903 100644 --- a/verifying/blocking/verifiers/mutex_verifier.h +++ b/verifying/blocking/verifiers/mutex_verifier.h @@ -5,7 +5,7 @@ struct MutexVerifier { bool Verify(CreatedTaskMetaData ctask) { auto [taskName, is_new, thread_id] = ctask; - debug(stderr, "validating method %s, thread_id: %zu\n", taskName.data(), + DEBUG(stderr, "validating method %s, thread_id: %zu\n", taskName.data(), thread_id); if (!is_new) { return true; @@ -25,7 +25,7 @@ struct MutexVerifier { void OnFinished(TaskWithMetaData ctask) { auto [task, is_new, thread_id] = ctask; auto taskName = task->GetName(); - debug(stderr, "On finished method %s, thread_id: %zu\n", taskName.data(), + DEBUG(stderr, "On finished method %s, thread_id: %zu\n", taskName.data(), thread_id); if (taskName == "Lock") { status[thread_id] = 1; diff --git a/verifying/blocking/verifiers/shared_mutex_verifier.h b/verifying/blocking/verifiers/shared_mutex_verifier.h index b2d34ba7..7d9616af 100644 --- a/verifying/blocking/verifiers/shared_mutex_verifier.h +++ b/verifying/blocking/verifiers/shared_mutex_verifier.h @@ -7,7 +7,7 @@ struct SharedMutexVerifier { /// Verify checks the state of a mutex on starting of `ctask` bool Verify(CreatedTaskMetaData ctask) { auto [taskName, is_new, thread_id] = ctask; - debug(stderr, "validating method %s, thread_id: %zu\n", taskName.data(), + DEBUG(stderr, "validating method %s, thread_id: %zu\n", taskName.data(), thread_id); if (status.count(thread_id) == 0) { status[thread_id] = FREE; @@ -30,7 +30,7 @@ struct SharedMutexVerifier { void OnFinished(TaskWithMetaData ctask) { auto [task, is_new, thread_id] = ctask; auto taskName = task->GetName(); - debug(stderr, "On finished method %s, thread_id: %zu\n", taskName.data(), + DEBUG(stderr, "On finished method %s, thread_id: %zu\n", taskName.data(), thread_id); if (taskName == "lock") { status[thread_id] = WRITER; diff --git a/verifying/specs/bounded_queue.h b/verifying/specs/bounded_queue.h index 274fdddc..d31a6e1a 100644 --- a/verifying/specs/bounded_queue.h +++ b/verifying/specs/bounded_queue.h @@ -11,9 +11,9 @@ namespace spec { struct Queue; -using mutex_method_t = std::function; +using MutexMethodT = std::function; -const int size = 2; +constexpr int size = 2; struct Queue { std::deque deq{}; @@ -32,16 +32,16 @@ struct Queue { return res; } static auto GetMethods() { - mutex_method_t push_func = [](Queue *l, void *args) -> int { + MutexMethodT push_func = [](Queue *l, void *args) -> int { auto real_args = reinterpret_cast *>(args); return l->Push(std::get<0>(*real_args)); }; - mutex_method_t pop_func = [](Queue *l, void *args) -> int { + MutexMethodT pop_func = [](Queue *l, void *args) -> int { return l->Pop(); }; - return std::map{ + return std::map{ {"Push", push_func}, {"Pop", pop_func}, }; diff --git a/verifying/specs/mutex.h b/verifying/specs/mutex.h index 3b97f19d..62552051 100644 --- a/verifying/specs/mutex.h +++ b/verifying/specs/mutex.h @@ -8,7 +8,7 @@ namespace spec { struct LinearMutex; -using mutex_method_t = std::function; +using MutexMethodT = std::function; struct LinearMutex { private: @@ -28,15 +28,15 @@ struct LinearMutex { } static auto GetMethods() { - mutex_method_t lock_func = [](LinearMutex *l, void *) -> int { + MutexMethodT lock_func = [](LinearMutex *l, void *) -> int { return l->Lock(); }; - mutex_method_t unlock_func = [](LinearMutex *l, void *) -> int { + MutexMethodT unlock_func = [](LinearMutex *l, void *) -> int { return l->Unlock(); }; - return std::map{ + return std::map{ {"Lock", lock_func}, {"Unlock", unlock_func}, }; @@ -55,7 +55,7 @@ struct LinearMutexEquals { struct SharedLinearMutex; -using shared_mutex_method_t = std::function; +using SharedMutexMethodT = std::function; struct SharedLinearMutex { private: @@ -63,19 +63,19 @@ struct SharedLinearMutex { int locked_state = FREE; public: - int lock() { + int Lock() { if (locked_state != FREE) { return 1; } locked_state = WRITER; return 0; } - int unlock() { + int Unlock() { locked_state = FREE; return 0; } - int lock_shared() { + int LockShared() { if (locked_state == WRITER) { return 1; } @@ -83,26 +83,26 @@ struct SharedLinearMutex { return 0; } - int unlock_shared() { + int UnlockShared() { locked_state -= READER; return 0; } static auto GetMethods() { - shared_mutex_method_t lock_func = [](SharedLinearMutex *l, void *) -> int { - return l->lock(); + SharedMutexMethodT lock_func = [](SharedLinearMutex *l, void *) -> int { + return l->Lock(); }; - shared_mutex_method_t unlock_func = - [](SharedLinearMutex *l, void *) -> int { return l->unlock(); }; + SharedMutexMethodT unlock_func = + [](SharedLinearMutex *l, void *) -> int { return l->Unlock(); }; - shared_mutex_method_t shared_lock_func = - [](SharedLinearMutex *l, void *) -> int { return l->lock_shared(); }; + SharedMutexMethodT shared_lock_func = + [](SharedLinearMutex *l, void *) -> int { return l->LockShared(); }; - shared_mutex_method_t shared_unlock_func = - [](SharedLinearMutex *l, void *) -> int { return l->unlock_shared(); }; + SharedMutexMethodT shared_unlock_func = + [](SharedLinearMutex *l, void *) -> int { return l->UnlockShared(); }; - return std::map{ + return std::map{ {"lock", lock_func}, {"unlock", unlock_func}, {"lock_shared", shared_lock_func}, diff --git a/verifying/specs/queue.h b/verifying/specs/queue.h index c6111262..35491174 100644 --- a/verifying/specs/queue.h +++ b/verifying/specs/queue.h @@ -21,17 +21,17 @@ struct Queue { return res; } - using method_t = std::function; + using MethodT = std::function; static auto GetMethods() { - method_t push_func = [](Queue *l, void *args) -> ValueWrapper { + MethodT push_func = [](Queue *l, void *args) -> ValueWrapper { auto real_args = reinterpret_cast(args); l->Push(std::get(*real_args)); return void_v; }; - method_t pop_func = [](Queue *l, void *args) -> int { return l->Pop(); }; + MethodT pop_func = [](Queue *l, void *args) -> int { return l->Pop(); }; - return std::map{ + return std::map{ {"Push", push_func}, {"Pop", pop_func}, }; diff --git a/verifying/specs/register.h b/verifying/specs/register.h index 05646c77..ee060895 100644 --- a/verifying/specs/register.h +++ b/verifying/specs/register.h @@ -8,24 +8,24 @@ namespace spec { struct LinearRegister; -using mutex_method_t = std::function; +using MutexMethodT = std::function; struct LinearRegister { int x = 0; - void add() { ++x; } - int get() { return x; } + void Add() { ++x; } + int Get() { return x; } static auto GetMethods() { - mutex_method_t add_func = [](LinearRegister *l, void *) { - l->add(); + MutexMethodT add_func = [](LinearRegister *l, void *) { + l->Add(); return void_v; }; - mutex_method_t get_func = [](LinearRegister *l, void *) { - return l->get(); + MutexMethodT get_func = [](LinearRegister *l, void *) { + return l->Get(); }; - return std::map{ + return std::map{ {"add", add_func}, {"get", get_func}, }; diff --git a/verifying/specs/set.h b/verifying/specs/set.h index 1d5a8909..5ff154fe 100644 --- a/verifying/specs/set.h +++ b/verifying/specs/set.h @@ -17,19 +17,19 @@ struct Set { return how_many != 0; } - using method_t = std::function; + using MethodT = std::function; static auto GetMethods() { - method_t insert_func = [](Set *l, void *args) -> int { + MethodT insert_func = [](Set *l, void *args) -> int { auto real_args = reinterpret_cast(args); return l->Insert(std::get(*real_args)); }; - method_t erase_func = [](Set *l, void *args) -> int { + MethodT erase_func = [](Set *l, void *args) -> int { auto real_args = reinterpret_cast(args); return l->Erase(std::get(*real_args)); }; - return std::map{ + return std::map{ {"Insert", insert_func}, {"Erase", erase_func}, }; diff --git a/verifying/specs/stack.h b/verifying/specs/stack.h index 0f59d8d1..90a9b2c0 100644 --- a/verifying/specs/stack.h +++ b/verifying/specs/stack.h @@ -19,17 +19,17 @@ struct Stack { return res; } - using method_t = std::function; + using MethodT = std::function; static auto GetMethods() { - method_t push_func = [](Stack *l, void *args) -> ValueWrapper { + MethodT push_func = [](Stack *l, void *args) -> ValueWrapper { auto real_args = reinterpret_cast(args); l->Push(std::get(*real_args)); return void_v; }; - method_t pop_func = [](Stack *l, void *args) -> int { return l->Pop(); }; + MethodT pop_func = [](Stack *l, void *args) -> int { return l->Pop(); }; - return std::map{ + return std::map{ {"Push", push_func}, {"Pop", pop_func}, }; diff --git a/verifying/targets/atomic_register.cpp b/verifying/targets/atomic_register.cpp index f328f7c5..31a3f588 100644 --- a/verifying/targets/atomic_register.cpp +++ b/verifying/targets/atomic_register.cpp @@ -7,20 +7,20 @@ #include "../specs/register.h" struct Register { - non_atomic void add() { x.fetch_add(1); } - non_atomic int get() { return x.load(); } + NON_ATOMIC void Add() { x.fetch_add(1); } + NON_ATOMIC int Get() { return x.load(); } void Reset() { x.store(0); } std::atomic x{}; }; -using spec_t = +using SpecT = ltest::Spec; -LTEST_ENTRYPOINT(spec_t); +LTEST_ENTRYPOINT(SpecT); -target_method(ltest::generators::genEmpty, void, Register, add); +TARGET_METHOD(ltest::generators::GenEmpty, void, Register, Add); -target_method(ltest::generators::genEmpty, int, Register, get); \ No newline at end of file +TARGET_METHOD(ltest::generators::GenEmpty, int, Register, Get); \ No newline at end of file diff --git a/verifying/targets/counique_args.cpp b/verifying/targets/counique_args.cpp index b599640e..5d97f05e 100644 --- a/verifying/targets/counique_args.cpp +++ b/verifying/targets/counique_args.cpp @@ -54,13 +54,13 @@ struct CoUniqueArgsTest { auto GenerateArgs(size_t thread_num) { for (size_t i = 0; i < limit; i++) { if (!used[i]) { - return ltest::generators::makeSingleArg(i); + return ltest::generators::MakeSingleArg(i); } } assert(false && "extra call"); } -target_method(GenerateArgs, int, CoUniqueArgsTest, Get, size_t); +TARGET_METHOD(GenerateArgs, int, CoUniqueArgsTest, Get, size_t); using SpecT = ltest::Spec token, int v) { + NON_ATOMIC void Lock(std::shared_ptr token, int v) { if (v % 2 == 0) { mu1.Lock(token); CoroYield(); @@ -38,32 +38,32 @@ struct Test { Mutex mu1, mu2{}; - using method_t = std::function; + using MethodT = std::function; static auto GetMethods() { - method_t lock_func = [](Test *l, void *args) -> int { + MethodT lock_func = [](Test *l, void *args) -> int { // `void` return type is always return 0 equivalent. return 0; }; - return std::map{ + return std::map{ {"Lock", lock_func}, }; } }; -auto generateInt(size_t thread_num) { - return ltest::generators::makeSingleArg(static_cast(thread_num)); +auto GenerateInt(size_t thread_num) { + return ltest::generators::MakeSingleArg(static_cast(thread_num)); } -auto generateArgs(size_t thread_num) { - auto token = ltest::generators::genToken(thread_num); - auto _int = generateInt(thread_num); - return std::tuple_cat(token, _int); +auto GenerateArgs(size_t thread_num) { + auto token = ltest::generators::GenToken(thread_num); + auto gen_int = GenerateInt(thread_num); + return std::tuple_cat(token, gen_int); } -using spec_t = ltest::Spec; +using SpecT = ltest::Spec; -LTEST_ENTRYPOINT(spec_t); +LTEST_ENTRYPOINT(SpecT); -target_method(generateArgs, void, Test, Lock, std::shared_ptr, int); \ No newline at end of file +TARGET_METHOD(GenerateArgs, void, Test, Lock, std::shared_ptr, int); \ No newline at end of file diff --git a/verifying/targets/fast_queue.cpp b/verifying/targets/fast_queue.cpp index 180a421e..a6da0139 100644 --- a/verifying/targets/fast_queue.cpp +++ b/verifying/targets/fast_queue.cpp @@ -24,40 +24,40 @@ struct Node { } }; -const int size = 2; +constexpr int size = 2; -auto generateInt(size_t thread_num) { - return ltest::generators::makeSingleArg(rand() % 10 + 1); +auto GenerateInt(size_t thread_num) { + return ltest::generators::MakeSingleArg(rand() % 10 + 1); } class MPMCBoundedQueue { public: - explicit MPMCBoundedQueue() : max_size_{size - 1} { - vec_.resize(size); + explicit MPMCBoundedQueue() : max_size{size - 1} { + vec.resize(size); for (size_t i = 0; i < size; ++i) { - vec_[i].generation.store(i, std::memory_order_relaxed); + vec[i].generation.store(i, std::memory_order_relaxed); } } void Reset() { for (size_t i = 0; i < size; ++i) { - vec_[i].generation.store(i); + vec[i].generation.store(i); } - head_.store(0); - tail_.store(0); + head.store(0); + tail.store(0); } - non_atomic int Push(int value) { + NON_ATOMIC int Push(int value) { while (true) { - auto h = head_.load(/*std::memory_order_relaxed*/); - auto hid = h & max_size_; - auto gen = vec_[hid].generation.load(/*std::memory_order_relaxed*/); + auto h = head.load(/*std::memory_order_relaxed*/); + auto hid = h & max_size; + auto gen = vec[hid].generation.load(/*std::memory_order_relaxed*/); if (gen == h) { - if (head_.compare_exchange_weak( - h, h + 1 /*, std::memory_order_acquire*/)) { + if (head.compare_exchange_weak(h, + h + 1 /*, std::memory_order_acquire*/)) { // I am owner of the element. - vec_[hid].val = value; - vec_[hid].generation.fetch_add(1 /*, std::memory_order_release*/); + vec[hid].val = value; + vec[hid].generation.fetch_add(1 /*, std::memory_order_release*/); return true; } } else if (gen < h) { @@ -66,17 +66,17 @@ class MPMCBoundedQueue { } } - non_atomic int Pop() { + NON_ATOMIC int Pop() { while (true) { - auto t = tail_.load(/*std::memory_order_relaxed*/); - auto tid = t & max_size_; - auto gen = vec_[tid].generation.load(/*std::memory_order_relaxed*/); + auto t = tail.load(/*std::memory_order_relaxed*/); + auto tid = t & max_size; + auto gen = vec[tid].generation.load(/*std::memory_order_relaxed*/); if (gen == t + 1) { - if (tail_.compare_exchange_weak( + if (tail.compare_exchange_weak( t, t + 1 /*, std::memory_order_acquire*/)) { - int ret = std::move(vec_[tid].val); - vec_[tid].generation.fetch_add( - max_size_ /*, std::memory_order_release*/); + int ret = std::move(vec[tid].val); + vec[tid].generation.fetch_add( + max_size /*, std::memory_order_release*/); return ret; } } else { @@ -88,11 +88,11 @@ class MPMCBoundedQueue { } private: - size_t max_size_; - std::vector> vec_; + size_t max_size; + std::vector> vec; - std::atomic head_{}; - std::atomic tail_{}; + std::atomic head{}; + std::atomic tail{}; }; // 0 1 2 3 4 5 6 7 @@ -103,11 +103,11 @@ class MPMCBoundedQueue { // POP // 1 == tail + 1? 1 == 1 -using spec_t = ltest::Spec; +using SpecT = ltest::Spec; -LTEST_ENTRYPOINT(spec_t); +LTEST_ENTRYPOINT(SpecT); -target_method(generateInt, int, MPMCBoundedQueue, Push, int); +TARGET_METHOD(GenerateInt, int, MPMCBoundedQueue, Push, int); -target_method(ltest::generators::genEmpty, int, MPMCBoundedQueue, Pop); \ No newline at end of file +TARGET_METHOD(ltest::generators::GenEmpty, int, MPMCBoundedQueue, Pop); \ No newline at end of file diff --git a/verifying/targets/mutex_queue.cpp b/verifying/targets/mutex_queue.cpp index 8fda3395..2dd7cff5 100644 --- a/verifying/targets/mutex_queue.cpp +++ b/verifying/targets/mutex_queue.cpp @@ -1,5 +1,6 @@ /** - * ./build/verifying/targets/mutex_queue --tasks 4 --switches 1 --rounds 100000 --strategy tla + * ./build/verifying/targets/mutex_queue --tasks 4 --switches 1 --rounds 100000 + * --strategy tla */ #include #include @@ -7,10 +8,11 @@ #include "../lib/mutex.h" #include "../specs/queue.h" -const int N = 100; +constexpr int n = 100; struct Queue { - non_atomic void Push(std::shared_ptr token, int v) { + Queue() { a.fill(0); } + NON_ATOMIC void Push(std::shared_ptr token, int v) { mutex.Lock(token); a[head++] = v; ++cnt; @@ -19,7 +21,7 @@ struct Queue { mutex.Unlock(); } - non_atomic int Pop(std::shared_ptr token) { + NON_ATOMIC int Pop(std::shared_ptr token) { mutex.Lock(token); int e = 0; if (head - tail > 0) { @@ -36,33 +38,33 @@ struct Queue { mutex = Mutex{}; tail = head = 0; cnt = 0; - std::fill(a, a + N, 0); + a.fill(0); } int cnt{}; Mutex mutex{}; int tail{}, head{}; - int a[N]{}; + std::array a; }; namespace ltest {} // namespace ltest -auto generateInt() { return ltest::generators::makeSingleArg(rand() % 10 + 1); } +auto GenerateInt() { return ltest::generators::MakeSingleArg(rand() % 10 + 1); } -auto generateArgs(size_t thread_num) { - auto token = ltest::generators::genToken(thread_num); - auto _int = generateInt(); - return std::tuple_cat(token, _int); +auto GenerateArgs(size_t thread_num) { + auto token = ltest::generators::GenToken(thread_num); + auto gen_int = GenerateInt(); + return std::tuple_cat(token, gen_int); } using QueueCls = spec::Queue, int>, 1>; -using spec_t = ltest::Spec, - spec::QueueEquals>; +using SpecT = ltest::Spec, + spec::QueueEquals>; -LTEST_ENTRYPOINT(spec_t); +LTEST_ENTRYPOINT(SpecT); -target_method(generateArgs, void, Queue, Push, std::shared_ptr, int); +TARGET_METHOD(GenerateArgs, void, Queue, Push, std::shared_ptr, int); -target_method(ltest::generators::genToken, int, Queue, Pop, +TARGET_METHOD(ltest::generators::GenToken, int, Queue, Pop, std::shared_ptr); diff --git a/verifying/targets/nonlinear_ms_queue.cpp b/verifying/targets/nonlinear_ms_queue.cpp index 06e360ff..9db5d416 100644 --- a/verifying/targets/nonlinear_ms_queue.cpp +++ b/verifying/targets/nonlinear_ms_queue.cpp @@ -15,7 +15,7 @@ struct MSQueue { // all nodes are stored in a fixed sized vector, // big enough to store reasonable number of nodes. // The memory is cleared by the vector destructor between rounds. - const int N = 100; + static constexpr int n = 100; // Fixed-size vector to store nodes std::vector nodes; @@ -30,78 +30,78 @@ struct MSQueue { std::atomic index; // Helper function to get the next available node from the pool - non_atomic Node* allocateNode(int value) { - int currentIndex = index.fetch_add(1); // Atomically increment the index - assert(currentIndex < nodes.size() && "Node pool exhausted"); + NON_ATOMIC Node* AllocateNode(int value) { + int current_index = index.fetch_add(1); // Atomically increment the index + assert(current_index < nodes.size() && "Node pool exhausted"); - Node* node = &nodes[currentIndex]; + Node* node = &nodes[current_index]; node->value = value; node->next.store(nullptr); return node; } public: - MSQueue() : nodes(N), index(0) { + MSQueue() : nodes(n), index(0) { head.store(&dummyNode); tail.store(&dummyNode); } - non_atomic void Push(int value) { - Node* newNode = allocateNode(value); - Node* currentTail = nullptr; - Node* currentNext = nullptr; + NON_ATOMIC void Push(int value) { + Node* new_node = AllocateNode(value); + Node* current_tail = nullptr; + Node* current_next = nullptr; while (true) { - currentTail = tail.load(); - currentNext = currentTail->next.load(); + current_tail = tail.load(); + current_next = current_tail->next.load(); // Check if tail is still consistent - if (currentTail == tail.load()) { - if (currentNext == nullptr) { + if (current_tail == tail.load()) { + if (current_next == nullptr) { // Try to link the new node at the end - if (currentTail->next.compare_exchange_strong(currentNext, newNode)) { + if (current_tail->next.compare_exchange_strong(current_next, new_node)) { // Successfully added the new node break; } } else { // Tail was not pointing to the last node, try to advance it - tail.compare_exchange_strong(currentTail, currentNext); + tail.compare_exchange_strong(current_tail, current_next); } } } // Try to move tail to the new node - tail.compare_exchange_strong(currentTail, newNode); + tail.compare_exchange_strong(current_tail, new_node); } - non_atomic int Pop() { - Node* currentHead = nullptr; - Node* currentTail = nullptr; - Node* currentNext = nullptr; + NON_ATOMIC int Pop() { + Node* current_head = nullptr; + Node* current_tail = nullptr; + Node* current_next = nullptr; int value = 0; // MISTAKE int time = 0; while (time++ < 3 /* true */) { - currentHead = head.load(); - currentTail = tail.load(); - currentNext = currentHead->next.load(); + current_head = head.load(); + current_tail = tail.load(); + current_next = current_head->next.load(); // Check if head is still consistent - if (currentHead == head.load()) { - if (currentHead == currentTail) { + if (current_head == head.load()) { + if (current_head == current_tail) { // Queue might be empty or tail is lagging - if (currentNext == nullptr) { + if (current_next == nullptr) { return 0; // Queue is empty } // Tail is lagging, try to advance it - tail.compare_exchange_strong(currentTail, currentNext); + tail.compare_exchange_strong(current_tail, current_next); } else { // Read the value before CAS to avoid use-after-free - value = currentNext->value; + value = current_next->value; // Try to move head to the next node - if (head.compare_exchange_strong(currentHead, currentNext)) { + if (head.compare_exchange_strong(current_head, current_next)) { break; } } @@ -121,16 +121,16 @@ struct MSQueue { }; // Arguments generator. -auto generateInt(size_t unused) { - return ltest::generators::makeSingleArg(rand() % 10 + 1); +auto GenerateInt(size_t unused) { + return ltest::generators::MakeSingleArg(rand() % 10 + 1); } // Specify target structure and it's sequential specification. -using spec_t = +using SpecT = ltest::Spec, spec::QueueHash<>, spec::QueueEquals<>>; -LTEST_ENTRYPOINT(spec_t); +LTEST_ENTRYPOINT(SpecT); -target_method(generateInt, void, MSQueue, Push, int); +TARGET_METHOD(GenerateInt, void, MSQueue, Push, int); -target_method(ltest::generators::genEmpty, int, MSQueue, Pop); +TARGET_METHOD(ltest::generators::GenEmpty, int, MSQueue, Pop); diff --git a/verifying/targets/nonlinear_queue.cpp b/verifying/targets/nonlinear_queue.cpp index c3f126e2..e2497844 100644 --- a/verifying/targets/nonlinear_queue.cpp +++ b/verifying/targets/nonlinear_queue.cpp @@ -7,18 +7,18 @@ #include "../specs/queue.h" -const int N = 100; +constexpr int n = 100; // Implementation. struct Queue { Queue() {} - non_atomic void Push(int v) { + NON_ATOMIC void Push(int v) { int pos = head.fetch_add(1); a[pos] = v; } - non_atomic int Pop() { + NON_ATOMIC int Pop() { int last = head.load(); for (int i = 0; i < last; ++i) { int e = a[i].load(); @@ -31,24 +31,24 @@ struct Queue { void Reset() { head.store(0); - for (int i = 0; i < N; ++i) a[i].store(0); + for (int i = 0; i < n; ++i) a[i].store(0); } - std::atomic a[N]; + std::array, n> a; std::atomic head{}; }; // Arguments generator. -auto generateInt(size_t unused_param) { - return ltest::generators::makeSingleArg(rand() % 10 + 1); +auto GenerateInt(size_t unused_param) { + return ltest::generators::MakeSingleArg(rand() % 10 + 1); } // Specify target structure and it's sequential specification. -using spec_t = +using SpecT = ltest::Spec, spec::QueueHash<>, spec::QueueEquals<>>; -LTEST_ENTRYPOINT(spec_t); +LTEST_ENTRYPOINT(SpecT); -target_method(generateInt, void, Queue, Push, int); +TARGET_METHOD(GenerateInt, void, Queue, Push, int); -target_method(ltest::generators::genEmpty, int, Queue, Pop); \ No newline at end of file +TARGET_METHOD(ltest::generators::GenEmpty, int, Queue, Pop); \ No newline at end of file diff --git a/verifying/targets/nonlinear_set.cpp b/verifying/targets/nonlinear_set.cpp index 2697992a..433766f7 100644 --- a/verifying/targets/nonlinear_set.cpp +++ b/verifying/targets/nonlinear_set.cpp @@ -7,12 +7,12 @@ struct SlotsSet { public: SlotsSet() { Reset(); } - non_atomic int Insert(int value) { + NON_ATOMIC int Insert(int value) { assert(value != 0); // zero should never be added - size_t hash = value % N; - for (size_t i = 0; i < N; ++i) { - size_t idx = (hash + i) % N; + size_t hash = value % n; + for (size_t i = 0; i < n; ++i) { + size_t idx = (hash + i) % n; int current = slots[idx].load(); if (current == value) break; if (current == 0) { @@ -26,12 +26,12 @@ struct SlotsSet { return false; } - non_atomic int Erase(int value) { + NON_ATOMIC int Erase(int value) { assert(value != 0); - size_t hash = value % N; - for (size_t i = 0; i < N; ++i) { - size_t idx = (hash + i) % N; + size_t hash = value % n; + for (size_t i = 0; i < n; ++i) { + size_t idx = (hash + i) % n; int current = slots[idx].load(); if (current == value) { if (slots[idx].compare_exchange_strong(current, 0)) { @@ -46,18 +46,18 @@ struct SlotsSet { } void Reset() { - for (size_t i = 0; i < N; ++i) { + for (size_t i = 0; i < n; ++i) { slots[i].store(0); } } private: - static inline const int N = 100; - std::atomic slots[N]; + static constexpr int n = 100; + std::array, n> slots; }; // Arguments generator. -auto generateInt(size_t unused_param) { +auto GenerateInt(size_t unused_param) { // single value in arguments, because to find nonlinearizable // scenario we need 4 operations with the same argument // (which is pretty hard to find) @@ -75,15 +75,15 @@ auto generateInt(size_t unused_param) { | | <-- 1 | *--------------------*--------------------* */ - return ltest::generators::makeSingleArg(1); + return ltest::generators::MakeSingleArg(1); } // Specify target structure and it's sequential specification. -using spec_t = +using SpecT = ltest::Spec, spec::SetHash<>, spec::SetEquals<>>; -LTEST_ENTRYPOINT(spec_t); +LTEST_ENTRYPOINT(SpecT); -target_method(generateInt, int, SlotsSet, Insert, int); +TARGET_METHOD(GenerateInt, int, SlotsSet, Insert, int); -target_method(generateInt, int, SlotsSet, Erase, int); \ No newline at end of file +TARGET_METHOD(GenerateInt, int, SlotsSet, Erase, int); \ No newline at end of file diff --git a/verifying/targets/nonlinear_treiber_stack.cpp b/verifying/targets/nonlinear_treiber_stack.cpp index 66ab8c9d..e6d694a7 100644 --- a/verifying/targets/nonlinear_treiber_stack.cpp +++ b/verifying/targets/nonlinear_treiber_stack.cpp @@ -3,9 +3,9 @@ #include "../specs/stack.h" struct TreiberStack { - TreiberStack() : nodes(N), head(-1), free_list(0) { Reset(); } + TreiberStack() : nodes(n), head(-1), free_list(0) { Reset(); } - non_atomic void Push(int value) { + NON_ATOMIC void Push(int value) { int node_index; do { node_index = free_list.load(); @@ -25,7 +25,7 @@ struct TreiberStack { !head.compare_exchange_strong(old_head, node_index)); } - non_atomic int Pop() { + NON_ATOMIC int Pop() { int node_index; do { node_index = head.load(); @@ -66,23 +66,23 @@ struct TreiberStack { // all nodes are stored in a fixed sized vector, // big enough to store reasonable number of nodes. // The memory is cleared by the vector destructor between rounds. - const int N = 100; + static constexpr int n = 100; std::vector nodes; std::atomic head; std::atomic free_list; }; // Arguments generator. -auto generateInt(size_t thread_num) { - return ltest::generators::makeSingleArg(rand() % 10 + 1); +auto GenerateInt(size_t thread_num) { + return ltest::generators::MakeSingleArg(rand() % 10 + 1); } // Specify target structure and it's sequential specification. -using spec_t = ltest::Spec, spec::StackHash<>, +using SpecT = ltest::Spec, spec::StackHash<>, spec::StackEquals<>>; -LTEST_ENTRYPOINT(spec_t); +LTEST_ENTRYPOINT(SpecT); -target_method(generateInt, void, TreiberStack, Push, int); +TARGET_METHOD(GenerateInt, void, TreiberStack, Push, int); -target_method(ltest::generators::genEmpty, int, TreiberStack, Pop); \ No newline at end of file +TARGET_METHOD(ltest::generators::GenEmpty, int, TreiberStack, Pop); \ No newline at end of file diff --git a/verifying/targets/race_register.cpp b/verifying/targets/race_register.cpp index 844f3069..803ec149 100644 --- a/verifying/targets/race_register.cpp +++ b/verifying/targets/race_register.cpp @@ -2,21 +2,21 @@ #include "verifying/specs/register.h" struct Register { - non_atomic void add() { ++x; } + NON_ATOMIC void Add() { ++x; } - non_atomic int get() { return x; } + NON_ATOMIC int Get() { return x; } void Reset() { x = 0; } int x{}; }; -using spec_t = +using SpecT = ltest::Spec; -LTEST_ENTRYPOINT(spec_t); +LTEST_ENTRYPOINT(SpecT); -target_method(ltest::generators::genEmpty, void, Register, add); +TARGET_METHOD(ltest::generators::GenEmpty, void, Register, Add); -target_method(ltest::generators::genEmpty, int, Register, get); \ No newline at end of file +TARGET_METHOD(ltest::generators::GenEmpty, int, Register, Get); \ No newline at end of file diff --git a/verifying/targets/unique_args.cpp b/verifying/targets/unique_args.cpp index ee53dc8d..08a79bb9 100644 --- a/verifying/targets/unique_args.cpp +++ b/verifying/targets/unique_args.cpp @@ -33,13 +33,13 @@ struct CoUniqueArgsTest { auto GenerateArgs(size_t thread_num) { for (size_t i = 0; i < limit; i++) { if (!used[i]) { - return ltest::generators::makeSingleArg(i); + return ltest::generators::MakeSingleArg(i); } } assert(false && "extra call"); } -target_method(GenerateArgs, int, CoUniqueArgsTest, Get, size_t); +TARGET_METHOD(GenerateArgs, int, CoUniqueArgsTest, Get, size_t); using SpecT = ltest::Spec