diff --git a/examples/1_resources.cpp b/examples/1_resources.cpp index a7a79f8..1c7a0fc 100644 --- a/examples/1_resources.cpp +++ b/examples/1_resources.cpp @@ -6,6 +6,8 @@ */ #include +#include +#include #include @@ -13,13 +15,13 @@ int main(int, char*[]) { auto rg = redGrapes::init(1); - auto a = rg.createFieldResource>(); - auto b = rg.createIOResource(); - auto c = rg.createIOResource(); + auto a = redGrapes::FieldResource>(); + auto b = redGrapes::IOResource(); + auto c = redGrapes::IOResource(); redGrapes::ResourceUser user1( {a.read(), // complete resource - a.write().area({0}, {10}), // write only indices 0 to 10 + a.write({0}, {10}), // write only indices 0 to 10 b.write()}, 0, 0); diff --git a/examples/3_functors_with_resources.cpp b/examples/3_functors_with_resources.cpp index 8fc35cb..cf4271d 100644 --- a/examples/3_functors_with_resources.cpp +++ b/examples/3_functors_with_resources.cpp @@ -17,8 +17,8 @@ int main(void) spdlog::set_level(spdlog::level::trace); auto rg = redGrapes::init(); - auto a = rg.createIOResource(); - auto b = rg.createIOResource(); + auto a = redGrapes::IOResource(); + auto b = redGrapes::IOResource(); for(int i = 0; i < 1; ++i) { diff --git a/examples/5_access_demotion.cpp b/examples/5_access_demotion.cpp index 7bd5500..975663a 100644 --- a/examples/5_access_demotion.cpp +++ b/examples/5_access_demotion.cpp @@ -6,7 +6,9 @@ */ #include +#include #include +#include #include #include @@ -18,23 +20,26 @@ int main(int, char*[]) { spdlog::set_level(spdlog::level::trace); auto rg = rg::init(); - auto a = rg.createIOResource(); - - rg.emplace_task( - [&](auto a) - { - std::cout << "f1 writes A" << std::endl; - std::this_thread::sleep_for(std::chrono::seconds(1)); - - std::cout << "f1 now only reads A" << std::endl; - rg.update_properties(decltype(rg)::RGTask::TaskProperties::Patch::Builder() - .remove_resources({a.write()}) - .add_resources({a.read()})); - std::this_thread::sleep_for(std::chrono::seconds(1)); - - std::cout << "f1 done" << std::endl; - }, - a.write()); + auto a = redGrapes::IOResource(); + + // Access demotion is not implemented + + // rg.emplace_task( + // [&](auto a) + // { + // std::cout << "f1 writes A" << std::endl; + // std::this_thread::sleep_for(std::chrono::seconds(1)); + + // std::cout << "f1 now only reads A" << std::endl; + // rg.update_properties(decltype(rg)::RGTask::TaskProperties::Patch::Builder() + // .remove_resources({a}) + // .add_resources({rg::newAccess(a, + // rg::access::IOAccess(rg::access::IOAccess::read))})); + // std::this_thread::sleep_for(std::chrono::seconds(1)); + + // std::cout << "f1 done" << std::endl; + // }, + // a.write()); rg.emplace_task( []([[maybe_unused]] auto a) diff --git a/examples/6_resource_scope.cpp b/examples/6_resource_scope.cpp index 283c973..eba02ef 100644 --- a/examples/6_resource_scope.cpp +++ b/examples/6_resource_scope.cpp @@ -15,13 +15,13 @@ namespace rg = redGrapes; int main() { auto rg = rg::init(1); - auto a = rg.createIOResource(); // scope-level=0 + auto a = redGrapes::IOResource(); // scope-level=0 rg.emplace_task( [&]([[maybe_unused]] auto a) { std::cout << "scope = " << rg.scope_depth() << std::endl; - auto b = rg.createIOResource(); // scope-level=1 + auto b = redGrapes::IOResource(); // scope-level=1 rg.emplace_task( [&](auto b) diff --git a/examples/7_event.cpp b/examples/7_event.cpp index 3012a14..855d705 100644 --- a/examples/7_event.cpp +++ b/examples/7_event.cpp @@ -8,6 +8,7 @@ #define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_OFF #include +#include #include #include diff --git a/examples/8_child_destruction.cpp b/examples/8_child_destruction.cpp index a18edbd..7c84848 100644 --- a/examples/8_child_destruction.cpp +++ b/examples/8_child_destruction.cpp @@ -17,27 +17,35 @@ int main() spdlog::set_level(spdlog::level::off); auto rg = redGrapes::init(1); - auto a = rg.createIOResource(1); + auto a = redGrapes::IOResource(1); rg.emplace_task( [&rg]([[maybe_unused]] auto a) { std::cout << "scope = " << rg.scope_depth() << " a = " << *a << std::endl; - + auto a2 = redGrapes::IOResource(a); rg.emplace_task( [&rg](auto a) { *a = 2; std::cout << "scope = " << rg.scope_depth() << " a = " << *a << std::endl; }, - a.write()); + a2.write()); rg.emplace_task( [&rg](auto a) { *a = 3; std::cout << "scope = " << rg.scope_depth() << " a = " << *a << std::endl; + auto a3 = redGrapes::IOResource(a); + rg.emplace_task( + [&rg](auto a) + { + std::cout << "scope = " << rg.scope_depth() << " a = " << *a << std::endl; + *a = 4; + }, + a3.write()); }, - a.write()); + a2.write()); *a = 4; std::cout << "scope = " << rg.scope_depth() << " a = " << *a << std::endl; diff --git a/examples/cholesky.cpp b/examples/cholesky.cpp index 6dc6f99..9b5891f 100644 --- a/examples/cholesky.cpp +++ b/examples/cholesky.cpp @@ -23,7 +23,7 @@ void print_matrix(std::vector> A, int nblks, int { for(int jb = 0; jb < blocksize; ++jb) { - std::cout << (*A[ja * nblks + ia])[jb * blocksize + ib] << "; "; + std::cout << (*A[ja * nblks + ia].getObject())[jb * blocksize + ib] << "; "; } } std::cout << std::endl; @@ -84,7 +84,8 @@ int main(int argc, char* argv[]) for(size_t ib = 0; ib < blksz; ++ib) for(size_t ja = 0; ja < nblks; ++ja) for(size_t jb = 0; jb < blksz; ++jb) - (*A[ja * nblks + ia])[jb * blksz + ib] = Alin[(ia * blksz + ib) + (ja * blksz + jb) * N]; + (*A[ja * nblks + ia].getObject())[jb * blksz + ib] + = Alin[(ia * blksz + ib) + (ja * blksz + jb) * N]; print_matrix(A, nblks, blksz); diff --git a/examples/game_of_life.cpp b/examples/game_of_life.cpp index 1c5d29b..6b85a88 100644 --- a/examples/game_of_life.cpp +++ b/examples/game_of_life.cpp @@ -123,8 +123,8 @@ int main(int, char*[]) dst[{x + xi, y + yi}] = next_state((Cell const(*)[size.x + 2]) & (src[{x + xi, y + yi}])); }, - buffers[next].write().area({x, y}, {x + chunk_size.x, y + chunk_size.y}), - buffers[current].read().area({x - 1, y - 1}, {x + chunk_size.x + 2, y + chunk_size.y + 2})); + buffers[next].write({x, y}, {x + chunk_size.x, y + chunk_size.y}), + buffers[current].read({x - 1, y - 1}, {x + chunk_size.x + 2, y + chunk_size.y + 2})); current = next; } diff --git a/examples/mpi.cpp b/examples/mpi.cpp index d3afcd0..078e48f 100644 --- a/examples/mpi.cpp +++ b/examples/mpi.cpp @@ -140,7 +140,7 @@ int main() mpi_request_pool->get_status(request); }, - field[current].at({3}).read(), + field[current].read({3}), mpi_config.read()) .enable_stack_switching(); @@ -158,18 +158,18 @@ int main() int recv_data_count; MPI_Get_count(&status, MPI_CHAR, &recv_data_count); }, - field[current].at({0}).write(), + field[current].write({0}), mpi_config.read()) .enable_stack_switching(); /* * Compute iteration */ - for(size_t i = 1; i < field[current]->size(); ++i) + for(size_t i = 1; i < field[current].getObject()->size(); ++i) rg.emplace_task( [i](auto dst, auto src) { dst[{i}] = src[{i - 1}]; }, - field[next].at({i}).write(), - field[current].at({i - 1}).read()); + field[next].write({i}), + field[current].read({i - 1})); /* * Write Output diff --git a/redGrapes/SchedulerDescription.hpp b/redGrapes/SchedulerDescription.hpp index 150dbf9..be3b9a0 100644 --- a/redGrapes/SchedulerDescription.hpp +++ b/redGrapes/SchedulerDescription.hpp @@ -29,7 +29,7 @@ namespace redGrapes using Key = TTag; using ValueType = TScheduler; - SchedulerDescription(std::shared_ptr scheduler, TTag = DefaultTag{}) : scheduler{scheduler} + SchedulerDescription(std::shared_ptr const& scheduler, TTag = DefaultTag{}) : scheduler{scheduler} { } diff --git a/redGrapes/redGrapes.hpp b/redGrapes/redGrapes.hpp index ae287a2..2879734 100644 --- a/redGrapes/redGrapes.hpp +++ b/redGrapes/redGrapes.hpp @@ -10,8 +10,6 @@ #include "redGrapes/SchedulerDescription.hpp" #include "redGrapes/TaskFreeCtx.hpp" #include "redGrapes/globalSpace.hpp" -#include "redGrapes/resource/fieldresource.hpp" -#include "redGrapes/resource/ioresource.hpp" #include "redGrapes/scheduler/event.hpp" #include "redGrapes/scheduler/pool_scheduler.hpp" #include "redGrapes/task/task.hpp" @@ -139,7 +137,10 @@ namespace redGrapes SPDLOG_TRACE("emplace task to worker {}", worker_id); - using Impl = typename std::invoke_result_t, Callable, Args...>; + using Impl = typename std::invoke_result_t< + BindArgs()))...>, + Callable, + decltype(forward_arg(std::declval()))...>; // this is not set to nullptr. But it goes out of scope. Memory is managed by allocate FunTask* task; memory::Allocator alloc(worker_id); @@ -154,10 +155,10 @@ namespace redGrapes new(task) FunTask(worker_id, scope_depth_impl(), *scheduler_map[TSchedTag{}]); return TaskBuilder( - task, - current_task_space(), - std::forward(f), - std::forward(args)...); + task, + current_task_space(), + std::forward(f), + std::forward(args)...); } template @@ -177,30 +178,6 @@ namespace redGrapes return getScheduler(); } - template - auto createFieldResource(Container* c) -> FieldResource - { - return FieldResource(c); - } - - template - auto createFieldResource(Args&&... args) -> FieldResource - { - return FieldResource(std::forward(args)...); - } - - template - auto createIOResource(std::shared_ptr o) -> IOResource - { - return IOResource(o); - } - - template - auto createIOResource(Args&&... args) -> IOResource - { - return IOResource(std::forward(args)...); - } - template auto createResource() -> Resource { diff --git a/redGrapes/resource/access/field.hpp b/redGrapes/resource/access/field.hpp index ffbfb70..79293f6 100644 --- a/redGrapes/resource/access/field.hpp +++ b/redGrapes/resource/access/field.hpp @@ -11,9 +11,9 @@ #pragma once -#include "redGrapes/resource/access/area.hpp" #include "redGrapes/resource/access/combine.hpp" #include "redGrapes/resource/access/io.hpp" +#include "redGrapes/resource/access/range.hpp" namespace redGrapes { @@ -21,7 +21,7 @@ namespace redGrapes { template - using FieldAccess = CombineAccess, And_t>; + using FieldAccess = CombineAccess, And_t>; } // namespace access diff --git a/redGrapes/resource/access/io.hpp b/redGrapes/resource/access/io.hpp index 891f58d..cf4a0ff 100644 --- a/redGrapes/resource/access/io.hpp +++ b/redGrapes/resource/access/io.hpp @@ -13,6 +13,8 @@ #include +#include + namespace redGrapes { namespace access @@ -22,7 +24,7 @@ namespace redGrapes */ struct IOAccess { - enum Mode + enum Mode : uint8_t { write, read, diff --git a/redGrapes/resource/access/area.hpp b/redGrapes/resource/access/range.hpp similarity index 70% rename from redGrapes/resource/access/area.hpp rename to redGrapes/resource/access/range.hpp index c18c2c8..271ec68 100644 --- a/redGrapes/resource/access/area.hpp +++ b/redGrapes/resource/access/range.hpp @@ -20,16 +20,16 @@ namespace redGrapes { namespace access { - - struct AreaAccess : std::array + // Must be in increasing order + struct RangeAccess : std::array { - AreaAccess() + RangeAccess() { (*this)[0] = std::numeric_limits::min(); (*this)[1] = std::numeric_limits::max(); } - AreaAccess(std::array a) : std::array(a) + RangeAccess(std::array a) : std::array(a) { } @@ -39,17 +39,17 @@ namespace redGrapes && (*this)[1] == std::numeric_limits::max(); } - static bool is_serial(AreaAccess const& a, AreaAccess const& b) + static bool is_serial(RangeAccess const& a, RangeAccess const& b) { - return (a[1] > b[0]) && (a[0] < b[1]); + return !((a[1] <= b[0]) || (a[0] >= b[1])); } - bool is_superset_of(AreaAccess const& a) const + bool is_superset_of(RangeAccess const& a) const { return (((*this)[0] <= a[0]) && ((*this)[1] >= a[1])); } - bool operator==(AreaAccess const& other) const + bool operator==(RangeAccess const& other) const { return (*this)[0] == other[0] && (*this)[1] == other[1]; } @@ -62,7 +62,7 @@ namespace redGrapes } // namespace redGrapes template<> -struct fmt::formatter +struct fmt::formatter { constexpr auto parse(format_parse_context& ctx) { @@ -70,7 +70,7 @@ struct fmt::formatter } template - auto format(redGrapes::access::AreaAccess const& acc, FormatContext& ctx) const + auto format(redGrapes::access::RangeAccess const& acc, FormatContext& ctx) { return fmt::format_to(ctx.out(), "{{ \"area\" : {{ \"begin\" : {}, \"end\" : {} }} }}", acc[0], acc[1]); } diff --git a/redGrapes/resource/fieldresource.hpp b/redGrapes/resource/fieldresource.hpp index bf0c4d8..f0c16c3 100644 --- a/redGrapes/resource/fieldresource.hpp +++ b/redGrapes/resource/fieldresource.hpp @@ -11,11 +11,12 @@ #pragma once -#include "redGrapes/TaskFreeCtx.hpp" #include "redGrapes/resource/access/field.hpp" #include "redGrapes/resource/resource.hpp" #include "redGrapes/util/traits.hpp" +#include + namespace redGrapes { @@ -38,280 +39,263 @@ namespace redGrapes return {v.size()}; } - static Item& get(std::vector& v, std::array index) + static Item& get(std::vector& v, std::array const& index) { return v[index[0]]; } }; - template - struct Field> + template + struct Field const> { using Item = T; static constexpr size_t dim = 1; - static Item& get(std::array& array, std::array index) + static std::array extent(std::vector& v) { - return array[index[0]]; + return {v.size()}; } - }; - template - struct Field, Ny>> - { - using Item = T; - static constexpr size_t dim = 2; - - static Item& get(std::array, Ny>& array, std::array index) + static Item const& get(std::vector const& v, std::array const& index) { - return array[index[1]][index[0]]; + return v[index[0]]; } }; - }; // namespace trait - - namespace fieldresource - { - - template - struct AreaGuard : SharedResourceObject::dim>> + template + struct Field> { - static constexpr size_t dim = trait::Field::dim; - using Item = typename trait::Field::Item; - using Index = std::array; + using Item = T; + static constexpr size_t dim = 1; - bool contains(Index index) const noexcept + static Item& get(std::array& array, std::array const& index) { - for(size_t d = 0; d < dim; d++) - { - if(index[d] < m_area[d][0] || index[d] >= m_area[d][1]) - return false; - } - return true; + return array[index[0]]; } + }; - protected: - AreaGuard(ResourceId id, std::shared_ptr const& obj) - : SharedResourceObject>(id, obj) - { - } + template + struct Field const> + { + using Item = T; + static constexpr size_t dim = 1; - template - AreaGuard(ResourceId id, Args&&... args) - : SharedResourceObject>(id, std::forward(args)...) + static Item const& get(std::array const& array, std::array const& index) { + return array[index[0]]; } + }; - AreaGuard( - Resource::dim>> const& res, - std::shared_ptr const& obj) - : SharedResourceObject>(res, obj) - { - } + template + struct Field, Ny>> + { + using Item = T; + static constexpr size_t dim = 2; - template - AreaGuard(Resource::dim>> const& res, Args&&... args) - : SharedResourceObject>(res, std::forward(args)...) + static Item& get(std::array, Ny>& array, std::array const& index) { + return array[index[1]][index[0]]; } + }; - AreaGuard(AreaGuard const& other, Index begin, Index end) - : SharedResourceObject>(other) - , m_area(other.make_area(begin, end)) - { - } + template + struct Field, Ny> const> + { + using Item = T; + static constexpr size_t dim = 2; - Item& get(Index index) const + static Item const& get( + std::array, Ny> const& array, + std::array const& index) { - if(!contains(index)) - throw std::out_of_range("invalid area access"); - - return trait::Field::get(*this->obj, index); + return array[index[1]][index[0]]; } + }; - access::ArrayAccess make_area(Index begin, Index end) const - { - std::array sub_area; - for(int d = 0; d < dim; ++d) - sub_area[d] = access::AreaAccess({begin[d], end[d]}); - - if(!m_area.is_superset_of(sub_area)) - throw std::out_of_range("invalid sub area"); - return access::ArrayAccess(sub_area); - } + }; // namespace trait - access::ArrayAccess m_area; - }; + namespace fieldaccess + { template - struct ReadGuard : AreaGuard + struct FieldAccessWrapper { static constexpr size_t dim = trait::Field::dim; - using typename AreaGuard::Index; - using typename AreaGuard::Item; - - ReadGuard read() const noexcept - { - return *this; - } + using Index = std::array; - ReadGuard area(Index begin, Index end) const + FieldAccessWrapper(std::shared_ptr container) : container(std::move(container)), m_area{} { - return ReadGuard(*this, begin, end); } - ReadGuard at(Index pos) const + FieldAccessWrapper( + std::shared_ptr container, + access::ArrayAccess area) + : container(std::move(container)) + , m_area{area} { - Index end = pos; - for(size_t d = 0; d < dim; ++d) - end[d]++; - return ReadGuard(*this, pos, end); } - Item const& operator[](Index index) const + auto* operator->() const noexcept { - return this->get(index); + return container.get(); } - Container const* operator->() const noexcept + auto& operator[](Index const& index) const { - return this->obj.get(); + return get(index); } - operator ResourceAccess() const noexcept + auto& get(Index const& index) const noexcept { - return this->make_access(access::FieldAccess(access::IOAccess::read, this->m_area)); - } + if(!contains(index)) + throw std::out_of_range("invalid area access"); - protected: - ReadGuard(ReadGuard const& other, Index begin, Index end) : AreaGuard(other, begin, end) - { + return trait::Field::get(*container, index); } - ReadGuard(ResourceId id, std::shared_ptr const& obj) : AreaGuard(id, obj) + private: + bool contains(Index index) const noexcept { + for(size_t d = 0; d < dim; d++) + { + if(index[d] < m_area[d][0] || index[d] >= m_area[d][1]) + return false; + } + return true; } - template - ReadGuard(ResourceId id, Args&&... args) : AreaGuard(id, std::forward(args)...) - { - } + std::shared_ptr container; + access::ArrayAccess m_area; + }; - ReadGuard( - Resource::dim>> const& res, - std::shared_ptr const& obj) - : AreaGuard(res, obj) - { - } + } // namespace fieldaccess - template - ReadGuard(Resource::dim>> const& res, Args&&... args) - : AreaGuard(res, std::forward(args)...) - { - } - }; + namespace fieldresource + { template - struct WriteGuard : ReadGuard + struct AreaGuard : SharedResourceObject::dim>> { static constexpr size_t dim = trait::Field::dim; - using typename ReadGuard::Index; - using typename ReadGuard::Item; - - WriteGuard write() const noexcept - { - return *this; - } - - WriteGuard area(Index begin, Index end) const - { - return WriteGuard(*this, begin, end); - } + using Item = typename trait::Field::Item; + using Index = std::array; - WriteGuard at(Index pos) const + AreaGuard(std::shared_ptr const& obj) + : SharedResourceObject>(obj) + , m_area{} { - Index end = pos; - for(size_t d = 0; d < dim; ++d) - end[d]++; - return WriteGuard(*this, pos, end); } - Item& operator[](Index index) const - { - return this->get(index); - } + template + requires(!(traits::is_specialization_of_v>, AreaGuard> + || std::is_same_v>, Container*>) ) - Container* operator->() const noexcept + AreaGuard(Args&&... args) + : SharedResourceObject>(std::forward(args)...) + , m_area{} { - return this->obj.get(); } - operator ResourceAccess() const noexcept + template + AreaGuard(AreaGuard const& res, std::shared_ptr const& obj) + : SharedResourceObject>(res, obj) + , m_area{} { - return this->make_access(access::FieldAccess(access::IOAccess::write, this->m_area)); } - protected: - WriteGuard(WriteGuard const& other, Index begin, Index end) : ReadGuard(other, begin, end) + template + AreaGuard(AreaGuard const& res, Args&&... args) + : SharedResourceObject>(res, std::forward(args)...) + , m_area{} { } - WriteGuard(ResourceId id, std::shared_ptr const& obj) : ReadGuard(id, obj) + access::ArrayAccess make_area(Index begin, Index end) const { - } + std::array sub_area; + for(int d = 0; d < dim; ++d) + sub_area[d] = access::RangeAccess({begin[d], end[d]}); - template - WriteGuard(ResourceId id, Args&&... args) : ReadGuard(id, std::forward(args)...) - { - } + if(!m_area.is_superset_of(sub_area)) + throw std::out_of_range("invalid sub area"); - WriteGuard( - Resource::dim>> const& res, - std::shared_ptr const& obj) - : ReadGuard(res, obj) - { + return access::ArrayAccess(sub_area); } - template - WriteGuard(Resource::dim>> const& res, Args&&... args) - : ReadGuard(res, std::forward(args)...) - { - } + protected: + access::ArrayAccess m_area; }; + } // namespace fieldresource template - struct FieldResource : fieldresource::WriteGuard + struct FieldResource : fieldresource::AreaGuard { static constexpr size_t dim = trait::Field::dim; + using typename fieldresource::AreaGuard::Index; + using typename fieldresource::AreaGuard::Item; - FieldResource(Container* c) - : fieldresource::WriteGuard(TaskFreeCtx::create_resource_uid(), std::shared_ptr(c)) + using fieldresource::AreaGuard::AreaGuard; + + auto access(access::FieldAccess mode) const noexcept { + return ResourceAccessPair>{ + this->obj, + this->res.make_access(mode)}; } - template - requires( - !(traits::is_specialization_of_v>, FieldResource> - || std::is_same_v>, Container*>) ) + auto read() const noexcept + { + return ResourceAccessPair>{ + this->obj, + this->res.make_access(access::FieldAccess( + access::IOAccess::read, + access::ArrayAccess{}))}; + } + + auto read(Index begin, Index end) const noexcept + { + return ResourceAccessPair>{ + this->obj, + this->res.make_access(access::FieldAccess(access::IOAccess::read, this->make_area(begin, end)))}; + } + + auto read(Index pos) const noexcept + { + Index end = pos; + for(size_t d = 0; d < dim; ++d) + end[d]++; + return ResourceAccessPair>{ + {this->obj, this->make_area(pos, end)}, + this->res.make_access(access::FieldAccess(access::IOAccess::read, this->make_area(pos, end)))}; + } - FieldResource(Args&&... args) - : fieldresource::WriteGuard(TaskFreeCtx::create_resource_uid(), std::forward(args)...) + auto write() const noexcept { + return ResourceAccessPair>{ + this->obj, + this->res.make_access(access::FieldAccess( + access::IOAccess::write, + access::ArrayAccess{}))}; } - template - FieldResource(FieldResource const& res, Container* c) - : fieldresource::WriteGuard(res, std::shared_ptr(c)) + auto write(Index begin, Index end) const noexcept { + return ResourceAccessPair>{ + this->obj, + this->res.make_access(access::FieldAccess(access::IOAccess::write, this->make_area(begin, end)))}; } - template - FieldResource(FieldResource const& res, Args&&... args) - : fieldresource::WriteGuard(res, std::forward(args)...) + auto write(Index pos) const noexcept { + Index end = pos; + for(size_t d = 0; d < dim; ++d) + end[d]++; + return ResourceAccessPair>{ + this->obj, + this->res.make_access(access::FieldAccess(access::IOAccess::write, this->make_area(pos, end)))}; } }; diff --git a/redGrapes/resource/ioresource.hpp b/redGrapes/resource/ioresource.hpp index 2d25e1c..502dfdd 100644 --- a/redGrapes/resource/ioresource.hpp +++ b/redGrapes/resource/ioresource.hpp @@ -11,151 +11,34 @@ #pragma once -#include "redGrapes/TaskFreeCtx.hpp" #include "redGrapes/resource/access/io.hpp" #include "redGrapes/resource/resource.hpp" -#include "redGrapes/util/traits.hpp" #include -#include #include namespace redGrapes { - namespace ioresource - { - - template - struct ReadGuard : public SharedResourceObject - { - operator ResourceAccess() const noexcept - { - return this->make_access(access::IOAccess::read); - } - - ReadGuard read() const noexcept - { - return *this; - } - - T const& operator*() const noexcept - { - return *this->obj; - } - - T const* operator->() const noexcept - { - return this->obj.get(); - } - - T const* get() const noexcept - { - return this->obj.get(); - } - - protected: - ReadGuard(ResourceId id, std::shared_ptr const& obj) - : SharedResourceObject(id, obj) - { - } - - template - ReadGuard(ResourceId id, Args&&... args) - : SharedResourceObject(id, std::forward(args)...) - { - } - - ReadGuard(Resource const& res, std::shared_ptr const& obj) - : SharedResourceObject(res, obj) - { - } - - template - ReadGuard(Resource const& res, Args&&... args) - : SharedResourceObject(res, std::forward(args)...) - { - } - }; - - template - struct WriteGuard : public ReadGuard - { - operator ResourceAccess() const noexcept - { - return this->make_access(access::IOAccess::write); - } - - WriteGuard write() const noexcept - { - return *this; - } - - T& operator*() const noexcept - { - return *this->obj; - } - - T* operator->() const noexcept - { - return this->obj.get(); - } - - T* get() const noexcept - { - return this->obj.get(); - } - - protected: - WriteGuard(ResourceId id, std::shared_ptr const& obj) : ReadGuard(id, obj) - { - } - - template - WriteGuard(ResourceId id, Args&&... args) : ReadGuard(id, std::forward(args)...) - { - } - - WriteGuard(Resource const& res, std::shared_ptr const& obj) : ReadGuard(res, obj) - { - } - - template - WriteGuard(Resource const& res, Args&&... args) - : ReadGuard(res, std::forward(args)...) - { - } - }; - - } // namespace ioresource template - struct IOResource : public ioresource::WriteGuard + struct IOResource : public SharedResourceObject { - IOResource(std::shared_ptr const& o) : ioresource::WriteGuard(TaskFreeCtx::create_resource_uid(), o) - { - } + using SharedResourceObject::SharedResourceObject; - template - requires( - !(traits::is_specialization_of_v>, IOResource> - || std::is_same_v>, std::shared_ptr>) ) - IOResource(Args&&... args) - : ioresource::WriteGuard(TaskFreeCtx::create_resource_uid(), std::forward(args)...) + auto read() const noexcept { + return ResourceAccessPair>{ + this->obj, + this->res.make_access(access::IOAccess::read)}; } - template - IOResource(IOResource const& res, std::shared_ptr const& obj) : ioresource::WriteGuard(res, obj) + auto write() const noexcept { + return ResourceAccessPair>{this->obj, this->res.make_access(access::IOAccess::write)}; } - - template - IOResource(IOResource const& res, Args&&... args) - : ioresource::WriteGuard(res, std::forward(args)...) - { - } - - }; // struct IOResource + template + IOResource(std::shared_ptr) -> IOResource; + } // namespace redGrapes diff --git a/redGrapes/resource/resource.hpp b/redGrapes/resource/resource.hpp index b37039f..be407fe 100644 --- a/redGrapes/resource/resource.hpp +++ b/redGrapes/resource/resource.hpp @@ -16,10 +16,12 @@ #include "redGrapes/sync/spinlock.hpp" #include "redGrapes/task/property/trait.hpp" #include "redGrapes/util/chunked_list.hpp" +#include "redGrapes/util/traits.hpp" #include #include +#include #include #include #include @@ -83,47 +85,95 @@ namespace redGrapes } }; - class ResourceAccess + struct AccessBase { - // https://stackoverflow.com/questions/16567212/why-does-the-standard-prohibit-friend-declarations-of-partial-specializations - template - friend class Resource; + AccessBase(boost::typeindex::type_index access_type, std::shared_ptr resource) + : access_type(access_type) + , resource(std::move(resource)) + { + } - private: - struct AccessBase + AccessBase(AccessBase&& other) : access_type(other.access_type), resource(std::move(other.resource)) { - AccessBase(boost::typeindex::type_index access_type, std::shared_ptr resource) - : access_type(access_type) - , resource(resource) - { - } + } - AccessBase(AccessBase&& other) : access_type(other.access_type), resource(std::move(other.resource)) - { - } + virtual ~AccessBase(){}; + virtual bool operator==(AccessBase const& r) const = 0; + + bool is_same_resource(AccessBase const& a) const + { + return this->resource == a.resource; + } - virtual ~AccessBase(){}; - virtual bool operator==(AccessBase const& r) const = 0; + virtual bool is_synchronizing() const = 0; + virtual bool is_serial(AccessBase const& r) const = 0; + virtual bool is_superset_of(AccessBase const& r) const = 0; + virtual std::string mode_format() const = 0; - bool is_same_resource(ResourceAccess::AccessBase const& a) const - { - return this->resource == a.resource; - } + boost::typeindex::type_index access_type; + std::shared_ptr resource; + }; // AccessBase + + template + struct Access : public AccessBase + { + Access(std::shared_ptr const& resource, AccessPolicy policy) + : AccessBase(boost::typeindex::type_id(), resource) + , policy(policy) + { + } - virtual bool is_synchronizing() const = 0; - virtual bool is_serial(AccessBase const& r) const = 0; - virtual bool is_superset_of(AccessBase const& r) const = 0; - virtual std::string mode_format() const = 0; + Access(Access&& other) noexcept + : AccessBase(std::move(std::forward(other))) // TODO check this + , policy(std::move(other.policy)) + { + } - boost::typeindex::type_index access_type; - std::shared_ptr resource; - }; // AccessBase + ~Access() override = default; + bool is_synchronizing() const override + { + return policy.is_synchronizing(); + } + + bool is_serial(AccessBase const& a_) const override + { + Access const& a + = *static_cast(&a_); // no dynamic cast needed, type checked in ResourceAccess + return this->is_same_resource(a) && AccessPolicy::is_serial(this->policy, a.policy); + } + + bool is_superset_of(AccessBase const& a_) const override + { + Access const& a + = *static_cast(&a_); // no dynamic cast needed, type checked in ResourceAccess + return this->is_same_resource(a) && this->policy.is_superset_of(a.policy); + } + + bool operator==(AccessBase const& a_) const override + { + Access const& a + = *static_cast(&a_); // no dynamic cast needed, type checked in ResourceAccess + + return (this->is_same_resource(a_) && this->policy == a.policy); + } + + std::string mode_format() const override + { + return fmt::format("{}", policy); + } + + AccessPolicy policy; + }; // struct Access + + class ResourceAccess + { + private: // todo use allocator!! std::shared_ptr obj; public: - ResourceAccess(std::shared_ptr obj) : obj(obj) + ResourceAccess(std::shared_ptr obj) : obj(std::move(obj)) { } @@ -142,7 +192,18 @@ namespace redGrapes return *this; } - static bool is_serial(ResourceAccess const& a, ResourceAccess const& b) + template + friend ResourceAccess newAccess(ResourceAccess const& x, AccessPolicy pol) + { + assert(x.obj->access_type == boost::typeindex::type_id()); + auto y = redGrapes::memory::alloc_shared_bind>( + mapping::map_resource_to_worker(x.obj->resource->id), + x.obj->resource, + pol); + return ResourceAccess(y); + } + + friend bool is_serial(ResourceAccess const& a, ResourceAccess const& b) { if(a.obj->access_type == b.obj->access_type) return a.obj->is_serial(*b.obj); @@ -180,9 +241,10 @@ namespace redGrapes return this->obj->mode_format(); } - std::shared_ptr get_resource() + // Doesn't share ownership + ResourceBase* get_resource_ptr() const { - return obj->resource; + return (obj->resource).get(); } /** @@ -206,6 +268,23 @@ namespace redGrapes } }; // class ResourceAccess + template + ResourceAccess newAccess(ResourceAccess const& x, AccessPolicy pol); + + bool is_serial(ResourceAccess const& a, ResourceAccess const& b); + + template + struct ResourceAccessPair : public std::pair + { + using std::pair::pair; + + operator ResourceAccess() const + { + return this->second; + } + + }; // namespace std::pair + namespace trait { @@ -266,60 +345,6 @@ namespace redGrapes class Resource { protected: - struct Access : public ResourceAccess::AccessBase - { - Access(std::shared_ptr resource, AccessPolicy policy) - : ResourceAccess::AccessBase(boost::typeindex::type_id(), resource) - , policy(policy) - { - } - - Access(Access&& other) - : ResourceAccess::AccessBase( - std::move(std::forward(other))) // TODO check this - , policy(std::move(other.policy)) - { - } - - ~Access() - { - } - - bool is_synchronizing() const override - { - return policy.is_synchronizing(); - } - - bool is_serial(typename ResourceAccess::AccessBase const& a_) const override - { - Access const& a - = *static_cast(&a_); // no dynamic cast needed, type checked in ResourceAccess - return this->is_same_resource(a) && AccessPolicy::is_serial(this->policy, a.policy); - } - - bool is_superset_of(typename ResourceAccess::AccessBase const& a_) const override - { - Access const& a - = *static_cast(&a_); // no dynamic cast needed, type checked in ResourceAccess - return this->is_same_resource(a) && this->policy.is_superset_of(a.policy); - } - - bool operator==(typename ResourceAccess::AccessBase const& a_) const override - { - Access const& a - = *static_cast(&a_); // no dynamic cast needed, type checked in ResourceAccess - - return (this->is_same_resource(a_) && this->policy == a.policy); - } - - std::string mode_format() const - { - return fmt::format("{}", policy); - } - - AccessPolicy policy; - }; // struct ThisResourceAccess - std::shared_ptr base; public: @@ -338,8 +363,10 @@ namespace redGrapes */ ResourceAccess make_access(AccessPolicy pol) const { - auto a - = redGrapes::memory::alloc_shared_bind(mapping::map_resource_to_worker(base->id), base, pol); + auto a = redGrapes::memory::alloc_shared_bind>( + mapping::map_resource_to_worker(base->id), + base, + pol); return ResourceAccess(a); } @@ -352,37 +379,51 @@ namespace redGrapes }; // class Resource template - struct SharedResourceObject : Resource + struct SharedResourceObject { - // protected: - std::shared_ptr obj; - - SharedResourceObject(ResourceId id, std::shared_ptr const& obj) : Resource(id), obj(obj) + SharedResourceObject(std::shared_ptr obj) : res{TaskFreeCtx::create_resource_uid()}, obj(std::move(obj)) { } template - SharedResourceObject(ResourceId id, Args&&... args) - : Resource(id) - , obj{memory::alloc_shared_bind(mapping::map_resource_to_worker(id), std::forward(args)...)} + requires(!(traits::is_specialization_of_v>, SharedResourceObject> + || std::is_same_v>, std::shared_ptr>) ) + SharedResourceObject(Args&&... args) + : res{TaskFreeCtx::create_resource_uid()} + , obj{memory::alloc_shared_bind( + mapping::map_resource_to_worker(res.resource_id()), + std::forward(args)...)} { } - SharedResourceObject(Resource const& res, std::shared_ptr const& obj) - : Resource{res} - , obj{obj} + template + SharedResourceObject(SharedResourceObject const& res, std::shared_ptr obj) + : res{res} + , obj{std::move(obj)} { } - template - SharedResourceObject(Resource const& res, Args&&... args) - : Resource{res} + template + requires(!(std::is_same_v>, std::shared_ptr>) ) + SharedResourceObject(SharedResourceObject const& res, Args&&... args) + : res{res} , obj{memory::alloc_shared_bind( mapping::map_resource_to_worker(res.resource_id()), std::forward(args)...)} { } + // DANGER! Gives access to ibject being held as a resource without any synchronization and scheduling + // Only to be used when you know what you are doing + auto& getObject() + { + return obj; + } + + protected: + Resource res; + std::shared_ptr obj; + }; // struct SharedResourceObject } // namespace redGrapes diff --git a/redGrapes/resource/resource_user.hpp b/redGrapes/resource/resource_user.hpp index 6655c1f..383e6ee 100644 --- a/redGrapes/resource/resource_user.hpp +++ b/redGrapes/resource/resource_user.hpp @@ -27,9 +27,11 @@ namespace redGrapes struct TaskSpace; + // unique_resources - list of ResourceUsageEntry Doesnt own Resource Base. + // access_list - list of ResourceAccess is responsible for resource base lifetime struct ResourceUsageEntry { - std::shared_ptr resource; + ResourceBase* resource; typename ChunkedList::MutBackwardIterator user_entry; friend bool operator==(ResourceUsageEntry const& a, ResourceUsageEntry const& b) @@ -65,14 +67,14 @@ namespace redGrapes add_resource_access(ra); } - void add_resource_access(ResourceAccess ra) + void add_resource_access(ResourceAccess const& ra) { this->access_list.push(ra); - std::shared_ptr r = ra.get_resource(); + auto* r = ra.get_resource_ptr(); unique_resources.push(ResourceUsageEntry{r, r->users.rend()}); } - void rm_resource_access(ResourceAccess ra) + void rm_resource_access(ResourceAccess const& ra) { this->access_list.erase(ra); } @@ -81,17 +83,17 @@ namespace redGrapes { for(auto ra = access_list.rbegin(); ra != access_list.rend(); ++ra) { - std::shared_ptr r = ra->get_resource(); + auto* r = ra->get_resource_ptr(); unique_resources.erase(ResourceUsageEntry{r, r->users.rend()}); unique_resources.push(ResourceUsageEntry{r, r->users.rend()}); } } - bool has_sync_access(std::shared_ptr const& res) + bool has_sync_access(ResourceBase* res) { for(auto ra = access_list.rbegin(); ra != access_list.rend(); ++ra) { - if(ra->get_resource() == res && ra->is_synchronizing()) + if(ra->get_resource_ptr() == res && ra->is_synchronizing()) return true; } return false; @@ -121,7 +123,7 @@ namespace redGrapes for(auto rb = b.access_list.crbegin(); rb != b.access_list.crend(); ++rb) { TRACE_EVENT("ResourceUser", "RA::is_serial"); - if(ResourceAccess::is_serial(*ra, *rb)) + if(is_serial(*ra, *rb)) return true; } return false; diff --git a/redGrapes/scheduler/pool_scheduler.hpp b/redGrapes/scheduler/pool_scheduler.hpp index c8119d1..38e2c70 100644 --- a/redGrapes/scheduler/pool_scheduler.hpp +++ b/redGrapes/scheduler/pool_scheduler.hpp @@ -55,7 +55,7 @@ namespace redGrapes WorkerId getNextWorkerID(); - void init(WorkerId base_id); + void init(WorkerId base_id) override; void startExecution(); diff --git a/redGrapes/scheduler/thread_scheduler.hpp b/redGrapes/scheduler/thread_scheduler.hpp index bd34b64..83c1a99 100644 --- a/redGrapes/scheduler/thread_scheduler.hpp +++ b/redGrapes/scheduler/thread_scheduler.hpp @@ -33,7 +33,7 @@ namespace redGrapes } ThreadScheduler(std::shared_ptr> workerThread) - : m_worker_thread(workerThread) + : m_worker_thread(std::move(workerThread)) { } @@ -86,7 +86,7 @@ namespace redGrapes return m_base_id; } - virtual void init(WorkerId base_id) + void init(WorkerId base_id) override { m_base_id = base_id; // TODO check if it was already initalized diff --git a/redGrapes/task/property/resource.hpp b/redGrapes/task/property/resource.hpp index 6777a43..6e5826f 100644 --- a/redGrapes/task/property/resource.hpp +++ b/redGrapes/task/property/resource.hpp @@ -49,7 +49,7 @@ namespace redGrapes return builder; } - inline PropertiesBuilder& add_resource(ResourceAccess access) + inline PropertiesBuilder& add_resource(ResourceAccess const& access) { (*builder.task) += access; return builder; diff --git a/redGrapes/task/task_builder.hpp b/redGrapes/task/task_builder.hpp index 5855155..ac03fc4 100644 --- a/redGrapes/task/task_builder.hpp +++ b/redGrapes/task/task_builder.hpp @@ -14,6 +14,7 @@ #include #include +#include namespace redGrapes { @@ -38,13 +39,37 @@ namespace redGrapes } }; + // Helper function to conditionally forward the argument + template + constexpr auto forward_arg(T&& arg) + { + if constexpr(traits::is_derived_from_pair_v>) + { + if constexpr(std::is_same_v::second_type, ResourceAccess>) + { + return std::forward(arg.first); + } + else + { + return std::forward(arg); + } + } + else + { + return std::forward(arg); + } + } + /* TASK BUILDER */ template struct TaskBuilder : TTask::TaskProperties::template Builder> { - using Impl = typename std::invoke_result_t, Callable, Args...>; - using Result = typename std::invoke_result_t; + using Impl = typename std::invoke_result_t< + BindArgs()))...>, + Callable, + decltype(forward_arg(std::declval()))...>; + using Result = typename std::invoke_result_t()))...>; std::shared_ptr space; FunTask* task; @@ -66,7 +91,9 @@ namespace redGrapes this->init_id(); // set impl - task->impl.emplace(BindArgs{}(std::move(f), std::forward(args)...)); + task->impl.emplace(BindArgs()))...>{}( + std::move(f), + forward_arg(std::forward(args))...)); } TaskBuilder(TaskBuilder& other) diff --git a/redGrapes/util/atomic_list.hpp b/redGrapes/util/atomic_list.hpp index 0ff7b4b..4689567 100644 --- a/redGrapes/util/atomic_list.hpp +++ b/redGrapes/util/atomic_list.hpp @@ -289,7 +289,7 @@ namespace redGrapes * and returns the previous head to which the new_head * is now linked. */ - auto append_item(std::shared_ptr new_head) + auto append_item(std::shared_ptr const& new_head) { TRACE_EVENT("Allocator", "AtomicList::append_item()"); std::shared_ptr old_head; @@ -306,7 +306,7 @@ namespace redGrapes } // append the first head item if not already exists - bool try_append_first_item(std::shared_ptr new_head) + bool try_append_first_item(std::shared_ptr const& new_head) { TRACE_EVENT("Allocator", "AtomicList::append_first_item()"); diff --git a/redGrapes/util/traits.hpp b/redGrapes/util/traits.hpp index 0c16d1a..33afb12 100644 --- a/redGrapes/util/traits.hpp +++ b/redGrapes/util/traits.hpp @@ -1,5 +1,14 @@ +/* Copyright 2024 Tapish Narwal + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + #pragma once + #include +#include namespace redGrapes::traits { @@ -29,4 +38,32 @@ namespace redGrapes::traits template using first_type_t = typename first_type::type; + template + struct is_pair : std::false_type + { + }; + + template + struct is_pair> : std::true_type + { + }; + + template + inline constexpr bool is_pair_v = is_pair::value; + + template + struct is_derived_from_pair : std::false_type + { + }; + + // Specialization for std::pair + template + struct is_derived_from_pair> : std::true_type + { + }; + + // Helper variable template for is_derived_from_pair + template + constexpr bool is_derived_from_pair_v = is_derived_from_pair::value; + } // namespace redGrapes::traits diff --git a/test/access.cpp b/test/access.cpp index 352a134..c510356 100644 --- a/test/access.cpp +++ b/test/access.cpp @@ -1,8 +1,8 @@ -#include #include #include #include +#include #include @@ -52,86 +52,86 @@ TEST_CASE("IOAccess") REQUIRE(IOAccess{IOAccess::amul}.is_superset_of(IOAccess{IOAccess::amul}) == true); } -TEST_CASE("AreaAccess") +TEST_CASE("RangeAccess") { // --[-----]--(-----)-- - REQUIRE(AreaAccess::is_serial(AreaAccess({10, 20}), AreaAccess({30, 40})) == false); - REQUIRE(AreaAccess({10, 20}).is_superset_of(AreaAccess({30, 40})) == false); + REQUIRE(RangeAccess::is_serial(RangeAccess({10, 20}), RangeAccess({30, 40})) == false); + REQUIRE(RangeAccess({10, 20}).is_superset_of(RangeAccess({30, 40})) == false); // --(-----)--[-----]-- - REQUIRE(AreaAccess::is_serial(AreaAccess({30, 40}), AreaAccess({10, 20})) == false); - REQUIRE(AreaAccess({30, 40}).is_superset_of(AreaAccess({10, 20})) == false); + REQUIRE(RangeAccess::is_serial(RangeAccess({30, 40}), RangeAccess({10, 20})) == false); + REQUIRE(RangeAccess({30, 40}).is_superset_of(RangeAccess({10, 20})) == false); // --[--(--]--)-- - REQUIRE(AreaAccess::is_serial(AreaAccess({10, 20}), AreaAccess({15, 25})) == true); - REQUIRE(AreaAccess({10, 20}).is_superset_of(AreaAccess({15, 25})) == false); + REQUIRE(RangeAccess::is_serial(RangeAccess({10, 20}), RangeAccess({15, 25})) == true); + REQUIRE(RangeAccess({10, 20}).is_superset_of(RangeAccess({15, 25})) == false); // --(--[--)--]-- - REQUIRE(AreaAccess::is_serial(AreaAccess({15, 25}), AreaAccess({10, 20})) == true); - REQUIRE(AreaAccess({15, 15}).is_superset_of(AreaAccess({10, 20})) == false); + REQUIRE(RangeAccess::is_serial(RangeAccess({15, 25}), RangeAccess({10, 20})) == true); + REQUIRE(RangeAccess({15, 15}).is_superset_of(RangeAccess({10, 20})) == false); // --[--(--)--]-- - REQUIRE(AreaAccess::is_serial(AreaAccess({10, 30}), AreaAccess({15, 25})) == true); - REQUIRE(AreaAccess({10, 30}).is_superset_of(AreaAccess({15, 25})) == true); + REQUIRE(RangeAccess::is_serial(RangeAccess({10, 30}), RangeAccess({15, 25})) == true); + REQUIRE(RangeAccess({10, 30}).is_superset_of(RangeAccess({15, 25})) == true); // --(--[--]--)-- - REQUIRE(AreaAccess::is_serial(AreaAccess({15, 25}), AreaAccess({10, 30})) == true); - REQUIRE(AreaAccess({15, 25}).is_superset_of(AreaAccess({10, 30})) == false); + REQUIRE(RangeAccess::is_serial(RangeAccess({15, 25}), RangeAccess({10, 30})) == true); + REQUIRE(RangeAccess({15, 25}).is_superset_of(RangeAccess({10, 30})) == false); } TEST_CASE("CombineAccess") { - using A = CombineAccess; + using A = CombineAccess; REQUIRE( A::is_serial( - A(IOAccess{IOAccess::read}, AreaAccess({10, 20})), - A(IOAccess{IOAccess::read}, AreaAccess({15, 25}))) + A(IOAccess{IOAccess::read}, RangeAccess({10, 20})), + A(IOAccess{IOAccess::read}, RangeAccess({15, 25}))) == false); REQUIRE( A::is_serial( - A(IOAccess{IOAccess::read}, AreaAccess({10, 20})), - A(IOAccess{IOAccess::write}, AreaAccess({15, 25}))) + A(IOAccess{IOAccess::read}, RangeAccess({10, 20})), + A(IOAccess{IOAccess::write}, RangeAccess({15, 25}))) == true); REQUIRE( A::is_serial( - A(IOAccess{IOAccess::read}, AreaAccess({10, 20})), - A(IOAccess{IOAccess::write}, AreaAccess({30, 40}))) + A(IOAccess{IOAccess::read}, RangeAccess({10, 20})), + A(IOAccess{IOAccess::write}, RangeAccess({30, 40}))) == false); REQUIRE( - A(IOAccess{IOAccess::read}, AreaAccess({10, 20})) - .is_superset_of(A(IOAccess{IOAccess::read}, AreaAccess({15, 25}))) + A(IOAccess{IOAccess::read}, RangeAccess({10, 20})) + .is_superset_of(A(IOAccess{IOAccess::read}, RangeAccess({15, 25}))) == false); REQUIRE( - A(IOAccess{IOAccess::write}, AreaAccess({10, 30})) - .is_superset_of(A(IOAccess{IOAccess::read}, AreaAccess({15, 25}))) + A(IOAccess{IOAccess::write}, RangeAccess({10, 30})) + .is_superset_of(A(IOAccess{IOAccess::read}, RangeAccess({15, 25}))) == true); - using B = CombineAccess; + using B = CombineAccess; REQUIRE( B::is_serial( - B(IOAccess{IOAccess::read}, AreaAccess({10, 20})), - B(IOAccess{IOAccess::read}, AreaAccess({30, 40}))) + B(IOAccess{IOAccess::read}, RangeAccess({10, 20})), + B(IOAccess{IOAccess::read}, RangeAccess({30, 40}))) == false); REQUIRE( B::is_serial( - B(IOAccess{IOAccess::read}, AreaAccess({10, 20})), - B(IOAccess{IOAccess::read}, AreaAccess({15, 25}))) + B(IOAccess{IOAccess::read}, RangeAccess({10, 20})), + B(IOAccess{IOAccess::read}, RangeAccess({15, 25}))) == true); REQUIRE( B::is_serial( - B(IOAccess{IOAccess::read}, AreaAccess({10, 20})), - B(IOAccess{IOAccess::write}, AreaAccess({15, 25}))) + B(IOAccess{IOAccess::read}, RangeAccess({10, 20})), + B(IOAccess{IOAccess::write}, RangeAccess({15, 25}))) == true); REQUIRE( B::is_serial( - B(IOAccess{IOAccess::read}, AreaAccess({10, 20})), - B(IOAccess{IOAccess::write}, AreaAccess({30, 40}))) + B(IOAccess{IOAccess::read}, RangeAccess({10, 20})), + B(IOAccess{IOAccess::write}, RangeAccess({30, 40}))) == true); } @@ -191,24 +191,24 @@ TEST_CASE("ArrayAccess") TEST_CASE("FieldAccess") { - using Arr = ArrayAccess; + using Arr = ArrayAccess; REQUIRE( FieldAccess<3>::is_serial( FieldAccess<3>( IOAccess{IOAccess::read}, - Arr({AreaAccess({0, 10}), AreaAccess({0, 10}), AreaAccess({0, 10})})), + Arr({RangeAccess({0, 10}), RangeAccess({0, 10}), RangeAccess({0, 10})})), FieldAccess<3>( IOAccess{IOAccess::read}, - Arr({AreaAccess({0, 10}), AreaAccess({0, 10}), AreaAccess({0, 10})}))) + Arr({RangeAccess({0, 10}), RangeAccess({0, 10}), RangeAccess({0, 10})}))) == false); REQUIRE( FieldAccess<3>::is_serial( FieldAccess<3>( IOAccess{IOAccess::write}, - Arr({AreaAccess({0, 10}), AreaAccess({0, 10}), AreaAccess({0, 10})})), + Arr({RangeAccess({0, 10}), RangeAccess({0, 10}), RangeAccess({0, 10})})), FieldAccess<3>( IOAccess{IOAccess::read}, - Arr({AreaAccess({0, 10}), AreaAccess({0, 10}), AreaAccess({0, 10})}))) + Arr({RangeAccess({0, 10}), RangeAccess({0, 10}), RangeAccess({0, 10})}))) == true); } diff --git a/test/random_graph.cpp b/test/random_graph.cpp index e2a4132..d4dc5e4 100644 --- a/test/random_graph.cpp +++ b/test/random_graph.cpp @@ -186,6 +186,6 @@ TEST_CASE("RandomGraph") rg.barrier(); for(unsigned i = 0; i < n_resources; ++i) - REQUIRE(*resources[i] == expected_hash[i]); + REQUIRE(*resources[i].getObject() == expected_hash[i]); } } diff --git a/test/resource.cpp b/test/resource.cpp index e10dd1f..03e7964 100644 --- a/test/resource.cpp +++ b/test/resource.cpp @@ -49,16 +49,16 @@ TEST_CASE("Resource ID") auto b = rg.createResource(); // same resource - REQUIRE(redGrapes::ResourceAccess::is_serial(a.make_access(Access{}), a.make_access(Access{})) == true); - REQUIRE(redGrapes::ResourceAccess::is_serial(b.make_access(Access{}), b.make_access(Access{})) == true); + REQUIRE(redGrapes::is_serial(a.make_access(Access{}), a.make_access(Access{})) == true); + REQUIRE(redGrapes::is_serial(b.make_access(Access{}), b.make_access(Access{})) == true); // same resource, but copied redGrapes::Resource a2(a); - REQUIRE(redGrapes::ResourceAccess::is_serial(a.make_access(Access{}), a2.make_access(Access{})) == true); + REQUIRE(redGrapes::is_serial(a.make_access(Access{}), a2.make_access(Access{})) == true); // different resource - REQUIRE(redGrapes::ResourceAccess::is_serial(a.make_access(Access{}), b.make_access(Access{})) == false); - REQUIRE(redGrapes::ResourceAccess::is_serial(b.make_access(Access{}), a.make_access(Access{})) == false); + REQUIRE(redGrapes::is_serial(a.make_access(Access{}), b.make_access(Access{})) == false); + REQUIRE(redGrapes::is_serial(b.make_access(Access{}), a.make_access(Access{})) == false); } TEST_CASE("IOResource") @@ -67,23 +67,23 @@ TEST_CASE("IOResource") redGrapes::IOResource a, b; - REQUIRE(redGrapes::ResourceAccess::is_serial(a.read(), a.read()) == false); - REQUIRE(redGrapes::ResourceAccess::is_serial(a.read(), a.write()) == true); - REQUIRE(redGrapes::ResourceAccess::is_serial(a.write(), a.read()) == true); - REQUIRE(redGrapes::ResourceAccess::is_serial(a.write(), a.write()) == true); - - REQUIRE(redGrapes::ResourceAccess::is_serial(b.read(), b.read()) == false); - REQUIRE(redGrapes::ResourceAccess::is_serial(b.read(), b.write()) == true); - REQUIRE(redGrapes::ResourceAccess::is_serial(b.write(), b.read()) == true); - REQUIRE(redGrapes::ResourceAccess::is_serial(b.write(), b.write()) == true); - - REQUIRE(redGrapes::ResourceAccess::is_serial(a.read(), b.read()) == false); - REQUIRE(redGrapes::ResourceAccess::is_serial(a.read(), b.write()) == false); - REQUIRE(redGrapes::ResourceAccess::is_serial(a.write(), b.read()) == false); - REQUIRE(redGrapes::ResourceAccess::is_serial(a.write(), b.write()) == false); - - REQUIRE(redGrapes::ResourceAccess::is_serial(b.read(), a.read()) == false); - REQUIRE(redGrapes::ResourceAccess::is_serial(b.read(), a.write()) == false); - REQUIRE(redGrapes::ResourceAccess::is_serial(b.write(), a.read()) == false); - REQUIRE(redGrapes::ResourceAccess::is_serial(b.write(), a.write()) == false); + REQUIRE(redGrapes::is_serial(a.read(), a.read()) == false); + REQUIRE(redGrapes::is_serial(a.read(), a.write()) == true); + REQUIRE(redGrapes::is_serial(a.write(), a.read()) == true); + REQUIRE(redGrapes::is_serial(a.write(), a.write()) == true); + + REQUIRE(redGrapes::is_serial(b.read(), b.read()) == false); + REQUIRE(redGrapes::is_serial(b.read(), b.write()) == true); + REQUIRE(redGrapes::is_serial(b.write(), b.read()) == true); + REQUIRE(redGrapes::is_serial(b.write(), b.write()) == true); + + REQUIRE(redGrapes::is_serial(a.read(), b.read()) == false); + REQUIRE(redGrapes::is_serial(a.read(), b.write()) == false); + REQUIRE(redGrapes::is_serial(a.write(), b.read()) == false); + REQUIRE(redGrapes::is_serial(a.write(), b.write()) == false); + + REQUIRE(redGrapes::is_serial(b.read(), a.read()) == false); + REQUIRE(redGrapes::is_serial(b.read(), a.write()) == false); + REQUIRE(redGrapes::is_serial(b.write(), a.read()) == false); + REQUIRE(redGrapes::is_serial(b.write(), a.write()) == false); }