...
 
Commits (67)
---
Language: Cpp
# BasedOnStyle: LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: true
AlignConsecutiveDeclarations: true
AlignEscapedNewlines: Right
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: MultiLine
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: true
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 0
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
- Regex: '.*'
Priority: 1
IncludeIsMainRegex: '(Test)?$'
IndentCaseLabels: false
IndentPPDirectives: None
IndentWidth: 4
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Left
ReflowComments: true
SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: Never
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp11
TabWidth: 8
UseTab: Never
...
......@@ -31,6 +31,8 @@ endmacro (use_cxx14)
use_cxx14 ()
add_definitions(-Wall -Wextra -Wpedantic)
# add our cmake module directory to the path
set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
"${CMAKE_CURRENT_SOURCE_DIR}/cmake")
......@@ -46,10 +48,15 @@ if (NOT CMAKE_BUILD_TYPE)
set_property (CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
"Debug" "Release" "RelWithDebInfo" "MinSizeRel")
endif ()
set (CMAKE_PREFIX_PATH "" CACHE STRING "External dependencies path")
set (BUILD_SHARED_LIBS "OFF" CACHE BOOL "Build a shared library")
option (ENABLE_CEREAL "Enable cereal serialization" OFF)
include_directories (${CMAKE_BINARY_DIR}/include)
# packages we depend on
if (ENABLE_CEREAL)
find_package (cereal CONFIG REQUIRED)
endif (ENABLE_CEREAL)
include (xpkg-import)
find_package (mercury CONFIG REQUIRED)
xpkg_import_module (margo REQUIRED margo)
......@@ -62,4 +69,4 @@ if (ENABLE_EXAMPLES)
add_subdirectory (examples)
endif (ENABLE_EXAMPLES)
configure_file (include/thallium/config.hpp.in ${CMAKE_BINARY_DIR}/include/thallium/config.hpp)
......@@ -2,7 +2,7 @@
namespace tl = thallium;
int main(int argc, char** argv) {
int main() {
tl::engine myEngine("tcp", THALLIUM_CLIENT_MODE);
......
......@@ -3,7 +3,7 @@
namespace tl = thallium;
int main(int argc, char** argv) {
int main() {
tl::engine myEngine("tcp", THALLIUM_SERVER_MODE);
std::cout << "Server running at address " << (std::string)myEngine.self() << std::endl;
......
......@@ -4,10 +4,11 @@
namespace tl = thallium;
void hello(const tl::request& req) {
(void)req;
std::cout << "Hello World!" << std::endl;
}
int main(int argc, char** argv) {
int main() {
tl::engine myEngine("tcp", THALLIUM_SERVER_MODE);
std::cout << "Server running at address " << myEngine.self() << std::endl;
......
......@@ -8,7 +8,7 @@ void sum(const tl::request& req, int x, int y) {
req.respond(x+y);
}
int main(int argc, char** argv) {
int main() {
tl::engine myEngine("tcp", THALLIUM_SERVER_MODE);
std::cout << "Server running at address " << myEngine.self() << std::endl;
......
......@@ -10,9 +10,12 @@ int main(int argc, char** argv) {
}
tl::engine myEngine("tcp", THALLIUM_CLIENT_MODE);
tl::remote_procedure sum = myEngine.define("sum");
tl::remote_procedure mult = myEngine.define("mult");
tl::endpoint server = myEngine.lookup(argv[1]);
int ret = sum.on(server)(42,63);
std::cout << "Server answered " << ret << std::endl;
std::cout << "Server answered (sum)" << ret << std::endl;
ret = mult.on(server)(42,63);
std::cout << "Server answered (mult)" << ret << std::endl;
return 0;
}
......
......@@ -3,7 +3,7 @@
namespace tl = thallium;
int main(int argc, char** argv) {
int main() {
tl::engine myEngine("tcp", THALLIUM_SERVER_MODE);
std::cout << "Server running at address " << myEngine.self() << std::endl;
......@@ -16,6 +16,11 @@ int main(int argc, char** argv) {
myEngine.define("sum", sum);
myEngine.define("mult", [](const tl::request& req, int x, int y) {
std::cout << "Computing " << x << "*" << y << std::endl;
req.respond(x*y);
});
return 0;
}
......@@ -3,7 +3,7 @@
namespace tl = thallium;
int main(int argc, char** argv) {
int main() {
tl::engine myEngine("tcp", THALLIUM_SERVER_MODE);
std::cout << "Server running at address " << myEngine.self() << std::endl;
......@@ -17,7 +17,7 @@ int main(int argc, char** argv) {
myEngine.define("sum", sum);
myEngine.on_finalize([]() { std::cout << "Finalization was called" << std::endl; });
myEngine.push_finalize_callback([]() { std::cout << "Finalization was called" << std::endl; });
return 0;
}
......
......@@ -6,10 +6,11 @@
namespace tl = thallium;
void hello(const tl::request& req, const std::string& name) {
(void)req;
std::cout << "Hello " << name << std::endl;
}
int main(int argc, char** argv) {
int main() {
tl::engine myEngine("tcp", THALLIUM_SERVER_MODE);
std::cout << "Server running at address " << myEngine.self() << std::endl;
......
......@@ -4,7 +4,7 @@
namespace tl = thallium;
int main(int argc, char** argv) {
int main() {
tl::engine myEngine("tcp", THALLIUM_SERVER_MODE);
std::cout << "Server running at address " << myEngine.self() << std::endl;
......
......@@ -4,7 +4,7 @@
namespace tl = thallium;
int main(int argc, char** argv) {
int main() {
tl::engine myEngine("tcp", THALLIUM_SERVER_MODE);
std::cout << "Server running at address " << myEngine.self() << std::endl;
......
......@@ -11,10 +11,24 @@ int main(int argc, char** argv) {
tl::engine myEngine("tcp", THALLIUM_CLIENT_MODE);
tl::remote_procedure sum = myEngine.define("sum");
tl::endpoint server = myEngine.lookup(argv[1]);
auto response = sum.on(server).async(42,63);
int ret = response.wait();
std::cout << "Server answered " << ret << std::endl;
std::vector<tl::async_response> reqs;
for(unsigned i=0; i < 10; i++) {
auto response = sum.on(server).async(42,63);
reqs.push_back(std::move(response));
}
for(auto i=0; i < 10; i++) {
int ret;
decltype(reqs.begin()) completed;
ret = tl::async_response::wait_any(reqs.begin(), reqs.end(), completed);
reqs.erase(completed);
std::cout << "Server answered " << ret << std::endl;
}
return 0;
}
#include <cstdlib>
#include <iostream>
#include <thallium.hpp>
namespace tl = thallium;
tl::engine theEngine;
void sum(const tl::request& req, int x, int y) {
std::cout << "Computing " << x << "+" << y << std::endl;
req.respond(x+y);
}
int main(int argc, char** argv) {
int main() {
tl::engine myEngine("tcp", THALLIUM_SERVER_MODE);
std::cout << "Server running at address " << myEngine.self() << std::endl;
myEngine.define("sum", sum);
theEngine = tl::engine("tcp", THALLIUM_SERVER_MODE);
std::cout << "Server running at address " << theEngine.self() << std::endl;
theEngine.define("sum", sum);
return 0;
}
......
......@@ -10,7 +10,7 @@ class my_sum_provider : public tl::provider<my_sum_provider> {
void prod(const tl::request& req, int x, int y) {
std::cout << "Computing " << x << "*" << y << std::endl;
req.respond(x+y);
req.respond(x*y);
}
int sum(int x, int y) const {
......@@ -29,7 +29,7 @@ class my_sum_provider : public tl::provider<my_sum_provider> {
public:
my_sum_provider(tl::engine& e, uint16_t provider_id=1)
my_sum_provider(const tl::engine& e, uint16_t provider_id=1)
: tl::provider<my_sum_provider>(e, provider_id) {
define("prod", &my_sum_provider::prod);
define("sum", &my_sum_provider::sum);
......@@ -38,11 +38,11 @@ class my_sum_provider : public tl::provider<my_sum_provider> {
}
~my_sum_provider() {
wait_for_finalize();
get_engine().wait_for_finalize();
}
};
int main(int argc, char** argv) {
int main() {
uint16_t provider_id = 22;
tl::engine myEngine("tcp", THALLIUM_SERVER_MODE);
......
......@@ -10,7 +10,7 @@ void hello() {
<< tl::thread::self_id() << std::endl;
}
int main(int argc, char** argv) {
int main() {
tl::abt scope;
......
......@@ -10,13 +10,14 @@ void hello() {
<< tl::task::self_id() << std::endl;
}
int main(int argc, char** argv) {
int main() {
tl::abt scope;
std::vector<tl::managed<tl::xstream>> ess;
tl::xstream primary = tl::xstream::self();
(void)primary;
for(int i=0; i < 4; i++) {
tl::managed<tl::xstream> es = tl::xstream::create();
......
......@@ -10,7 +10,7 @@ void hello() {
<< tl::thread::self_id() << std::endl;
}
int main(int argc, char** argv) {
int main() {
tl::abt scope;
......
......@@ -17,7 +17,7 @@ void hello(tl::mutex& mtx) {
mtx.unlock();
}
int main(int argc, char** argv) {
int main() {
tl::abt scope;
......
......@@ -16,10 +16,10 @@ class my_sched;
class my_unit {
tl::thread m_thread;
tl::task m_task;
tl::thread m_thread;
tl::task m_task;
tl::unit_type m_type;
bool m_in_pool;
bool m_in_pool;
friend class my_pool;
......@@ -56,6 +56,8 @@ class my_pool {
std::deque<my_unit*> m_units;
public:
static const tl::pool::access access_type = tl::pool::access::mpmc;
my_pool() {}
......@@ -145,21 +147,21 @@ void hello() {
<< std::endl;
}
int main(int argc, char** argv) {
int main() {
tl::abt scope;
// create pools
std::vector<tl::managed<tl::pool>> pools;
for(int i=0; i < NUM_XSTREAMS; i++) {
pools.push_back(tl::pool::create<tl::pool::access::mpmc, my_pool, my_unit>());
pools.push_back(tl::pool::create<my_pool, my_unit>());
}
// create schedulers
std::vector<tl::managed<tl::scheduler>> scheds;
for(int i=0; i < NUM_XSTREAMS; i++) {
for(unsigned i=0; i < NUM_XSTREAMS; i++) {
std::vector<tl::pool> pools_for_sched_i;
for(int j=0; j < pools.size(); j++) {
for(unsigned j=0; j < pools.size(); j++) {
pools_for_sched_i.push_back(*pools[j+i % pools.size()]);
}
scheds.push_back(tl::scheduler::create<my_scheduler>(pools_for_sched_i.begin(), pools_for_sched_i.end()));
......@@ -189,5 +191,9 @@ int main(int argc, char** argv) {
ess[i]->join();
}
ess.clear();
scheds.clear();
pools.clear();
return 0;
}
......@@ -8,7 +8,7 @@ void sum(const tl::request& req, int x, int y) {
req.respond(x+y);
}
int main(int argc, char** argv) {
int main() {
tl::abt scope;
......
......@@ -2,6 +2,7 @@
#define __THALLIUM_HPP
#include <margo.h>
#include <thallium/config.hpp>
#include <thallium/abt.hpp>
#include <thallium/anonymous.hpp>
#include <thallium/bulk_mode.hpp>
......
......@@ -7,8 +7,8 @@
#ifndef __THALLIUM_ABT_HPP
#define __THALLIUM_ABT_HPP
#include <thallium/exception.hpp>
#include <thallium/abt_errors.hpp>
#include <thallium/exception.hpp>
namespace thallium {
......@@ -16,62 +16,50 @@ namespace thallium {
* Exception class thrown by the abt class.
*/
class abt_exception : public exception {
public:
template<typename ... Args>
abt_exception(Args&&... args)
: exception(std::forward<Args>(args)...) {}
public:
template <typename... Args>
abt_exception(Args&&... args)
: exception(std::forward<Args>(args)...) {}
};
#define TL_ABT_EXCEPTION(__fun,__ret) \
abt_exception(#__fun," returned ", abt_error_get_name(__ret),\
" (", abt_error_get_description(__ret),") in ",__FILE__,":",__LINE__)
#define TL_ABT_EXCEPTION(__fun, __ret) \
abt_exception(#__fun, " returned ", abt_error_get_name(__ret), " (", \
abt_error_get_description(__ret), ") in ", __FILE__, ":", \
__LINE__)
#define TL_ABT_ASSERT(__call) {\
int __ret = __call; \
if(__ret != ABT_SUCCESS) {\
throw TL_ABT_EXCEPTION(__call, __ret);\
}\
}
#define TL_ABT_ASSERT(__call) \
{ \
int __ret = __call; \
if(__ret != ABT_SUCCESS) { \
throw TL_ABT_EXCEPTION(__call, __ret); \
} \
}
class abt {
public:
abt() {
initialize();
}
~abt() {
finalize();
}
/**
* @brief Initialize the Argobots execution environment.
*/
static void initialize() {
TL_ABT_ASSERT(ABT_init(0, nullptr));
}
/**
* @brief Check whether Argobots has been initialized.
*
* @return true if Argobots has been initialized.
*/
static bool initialized() {
return ABT_initialized() == ABT_TRUE;
}
/**
* @brief Finalizes Argobots.
*/
static void finalize() {
TL_ABT_ASSERT(ABT_finalize());
}
public:
abt() { initialize(); }
~abt() { finalize(); }
/**
* @brief Initialize the Argobots execution environment.
*/
static void initialize() { TL_ABT_ASSERT(ABT_init(0, nullptr)); }
/**
* @brief Check whether Argobots has been initialized.
*
* @return true if Argobots has been initialized.
*/
static bool initialized() { return ABT_initialized() == ABT_TRUE; }
/**
* @brief Finalizes Argobots.
*/
static void finalize() { TL_ABT_ASSERT(ABT_finalize()); }
};
}
} // namespace thallium
#undef TL_ABT_EXCEPTION
#undef TL_ABT_ASSERT
......
......@@ -6,29 +6,124 @@
#ifndef __THALLIUM_ABT_ERRORS_HPP
#define __THALLIUM_ABT_ERRORS_HPP
#include <abt.h>
namespace thallium {
/**
* @brief For internal use. Converts an error code
* returned by an Argobots function into a string name.
*
* @param err Error code
*
* @return Name of the error.
*/
const char* abt_error_get_name(int err);
/**
* @brief For internal use. Converts an error code
* returned by an Argobots function into a string description.
*
* @param err Error code
*
* @return Description of the error.
*/
const char* abt_error_get_description(int err);
inline const char* abt_error_get_name(int err) {
static const char* const abt_errors_names[] = {
"ABT_SUCCESS",
"ABT_ERR_UNINITIALIZED",
"ABT_ERR_MEM",
"ABT_ERR_OTHER",
"ABT_ERR_INV_XSTREAM",
"ABT_ERR_INV_XSTREAM_RANK",
"ABT_ERR_INV_XSTREAM_BARRIER",
"ABT_ERR_INV_SCHED",
"ABT_ERR_INV_SCHED_KIND",
"ABT_ERR_INV_SCHED_PREDEF",
"ABT_ERR_INV_SCHED_TYPE",
"ABT_ERR_INV_SCHED_CONFIG",
"ABT_ERR_INV_POOL",
"ABT_ERR_INV_POOL_KIND",
"ABT_ERR_INV_POOL_ACCESS",
"ABT_ERR_INV_UNIT",
"ABT_ERR_INV_THREAD",
"ABT_ERR_INV_THREAD_ATTR",
"ABT_ERR_INV_TASK",
"ABT_ERR_INV_KEY",
"ABT_ERR_INV_MUTEX",
"ABT_ERR_INV_MUTEX_ATTR",
"ABT_ERR_INV_COND",
"ABT_ERR_INV_RWLOCK",
"ABT_ERR_INV_EVENTUAL",
"ABT_ERR_INV_FUTURE",
"ABT_ERR_INV_BARRIER",
"ABT_ERR_INV_TIMER",
"ABT_ERR_INV_QUERY_KIND",
"ABT_ERR_XSTREAM",
"ABT_ERR_XSTREAM_STATE",
"ABT_ERR_XSTREAM_BARRIER",
"ABT_ERR_SCHED",
"ABT_ERR_SCHED_CONFIG",
"ABT_ERR_POOL",
"ABT_ERR_UNIT",
"ABT_ERR_THREAD",
"ABT_ERR_TASK",
"ABT_ERR_KEY",
"ABT_ERR_MUTEX",
"ABT_ERR_MUTEX_LOCKED",
"ABT_ERR_COND",
"ABT_ERR_COND_TIMEDOUT",
"ABT_ERR_RWLOCK",
"ABT_ERR_EVENTUAL",
"ABT_ERR_FUTURE",
"ABT_ERR_BARRIER",
"ABT_ERR_TIMER",
"ABT_ERR_MIGRATION_TARGET",
"ABT_ERR_MIGRATION_NA",
"ABT_ERR_MISSING_JOIN",
"ABT_ERR_FEATURE_NA" };
return abt_errors_names[err];
}
inline const char* abt_error_get_description(int err) {
static const char* const abt_error_descriptions[] = {
"Successful return code",
"Uninitialized",
"Memory allocation failure",
"Other error",
"Invalid ES",
"Invalid ES rank",
"Invalid ES barrier",
"Invalid scheduler",
"Invalid scheduler kind",
"Invalid predefined scheduler",
"Invalid scheduler type",
"Invalid scheduler config",
"Invalid pool",
"Invalid pool kind",
"Invalid pool access mode",
"Invalid scheduling unit",
"Invalid ULT",
"Invalid ULT attribute",
"Invalid tasklet",
"Invalid key",
"Invalid mutex",
"Invalid mutex attribute",
"Invalid condition variable",
"Invalid rw lock",
"Invalid eventual",
"Invalid future",
"Invalid barrier",
"Invalid timer",
"Invalid query kind",
"ES-related error",
"ES state error",
"ES barrier-related error",
"Scheduler-related error",
"Scheduler config error",
"Pool-related error",
"Scheduling unit-related error",
"ULT-related error",
"Task-related error",
"Key-related error",
"Mutex-related error",
"Return value when mutex is locked",
"Condition-related error",
"Return value when cond is timed out",
"Rwlock-related error",
"Eventual-related error",
"Future-related error",
"Barrier-related error",
"Timer-related error",
"Migration target error",
"Migration not available",
"An ES or more did not join",
"Feature not available"};
return abt_error_descriptions[err];
}
} // namespace thallium
#endif
......@@ -11,6 +11,6 @@ namespace thallium {
struct anonymous {};
}
} // namespace thallium
#endif
/*
* (C) 2017 The University of Chicago
*
*
* See COPYRIGHT in top-level directory.
*/
#ifndef __THALLIUM_ASYNC_RESPONSE_HPP
#define __THALLIUM_ASYNC_RESPONSE_HPP
#include <thallium/margo_exception.hpp>
#include <thallium/buffer.hpp>
#include <thallium/packed_response.hpp>
#include <thallium/serialization/serialize.hpp>
#include <thallium/serialization/stl/vector.hpp>
#include <thallium/serialization/buffer_output_archive.hpp>
#include <thallium/proc_object.hpp>
#include <thallium/timeout.hpp>
#include <utility>
#include <vector>
namespace thallium {
class callable_remote_procedure;
namespace detail {
struct engine_impl;
}
/**
* @brief async_response objects are created by sending an
* RPC in a non-blocking way. They can be used to wait for
* the actual response.
*/
class async_response {
friend class callable_remote_procedure;
private:
margo_request m_request;
engine* m_engine;
hg_handle_t m_handle;
bool m_ignore_response;
private:
margo_request m_request;
std::weak_ptr<detail::engine_impl> m_engine_impl;
hg_handle_t m_handle;
bool m_ignore_response;
/**
* @brief Constructor. Made private since async_response
......@@ -42,13 +44,16 @@ private:
* @param c callable_remote_procedure that created the async_response.
* @param ignore_resp whether response should be ignored.
*/
async_response(margo_request req, engine& e, hg_handle_t handle, bool ignore_resp)
: m_request(req), m_engine(&e), m_handle(handle), m_ignore_response(ignore_resp) {
async_response(margo_request req, std::weak_ptr<detail::engine_impl> e,
hg_handle_t handle, bool ignore_resp) noexcept
: m_request(req)
, m_engine_impl(std::move(e))
, m_handle(handle)
, m_ignore_response(ignore_resp) {
margo_ref_incr(handle);
}
public:
public:
/**
* @brief Copy constructor is deleted.
*/
......@@ -59,14 +64,13 @@ public:
*
* @param other async_response to move from.
*/
async_response(async_response&& other)
async_response(async_response&& other) noexcept
: m_request(other.m_request)
, m_engine(other.m_engine)
, m_engine_impl(std::move(other.m_engine_impl))
, m_handle(other.m_handle)
, m_ignore_response(other.m_ignore_response) {
other.m_request = MARGO_REQUEST_NULL;
other.m_engine = nullptr;
other.m_handle = HG_HANDLE_NULL;
other.m_handle = HG_HANDLE_NULL;
}
/**
......@@ -75,14 +79,27 @@ public:
async_response& operator=(const async_response& other) = delete;
/**
* @brief Move-assignment operator is deleted.
* @brief Move-assignment operator. Will invalidate
* the moved-from object.
*/
async_response& operator=(async_response&& other) = delete;
async_response& operator=(async_response&& other) noexcept {
if(this == &other)
return *this;
if(m_handle != HG_HANDLE_NULL)
margo_destroy(m_handle);
m_request = other.m_request;
m_engine_impl = std::move(other.m_engine_impl);
m_handle = other.m_handle;
m_ignore_response = other.m_ignore_response;
other.m_request = MARGO_REQUEST_NULL;
other.m_handle = HG_HANDLE_NULL;
return *this;
}
/**
* @brief Destructor.
*/
~async_response() {
~async_response() noexcept {
if(m_handle != HG_HANDLE_NULL)
margo_destroy(m_handle);
}
......@@ -93,7 +110,17 @@ public:
*
* @return a packed_response containing the response.
*/
packed_response wait();
packed_response wait() {
hg_return_t ret;
ret = margo_wait(m_request);
if(ret == HG_TIMEOUT) {
throw timeout();
}
MARGO_ASSERT(ret, margo_wait);
if(m_ignore_response)
return packed_response();
return packed_response(m_handle, m_engine_impl);
}
/**
* @brief Tests without blocking if the response has been received.
......@@ -107,8 +134,46 @@ public:
MARGO_ASSERT((hg_return_t)ret, margo_test);
return flag;
}
/**
* @brief Waits for any of the provided async_response to complete,
* and return a packed_response. The completed iterator will be set to point
* to the async_response that completed. This method may throw a timeout if
* any of the requests timed out, or other exceptions if an error happens.
* Even if an exception is thrown, the completed iterator will be correctly
* set to point to the async_response in cause.
*
* @tparam Iterator Iterator type (e.g.
* std::vector<async_response>::iterator)
* @param begin Begin iterator
* @param end End iterator
*
* @return a packed_response.
*/
template <typename Iterator>
static packed_response wait_any(const Iterator& begin, const Iterator& end,
Iterator& completed) {
std::vector<margo_request> reqs;
size_t count = std::distance(begin, end);
reqs.reserve(count);
for(auto it = begin; it != end; it++) {
reqs.push_back(it->m_request);
}
completed = begin;
size_t index = 0;
hg_return_t ret = margo_wait_any(count, reqs.data(), &index);
std::advance(completed, index);
if(ret == HG_TIMEOUT) {
throw timeout();
}
MARGO_ASSERT(ret, margo_wait_any);
if(completed->m_ignore_response) {
return packed_response();
}
return packed_response(completed->m_handle, completed->m_engine_impl);
}
};
}
} // namespace thallium
#endif
......@@ -17,34 +17,32 @@ namespace thallium {
* Exception class thrown by the barrier class.
*/
class barrier_exception : public exception {
public:
template<typename ... Args>
public:
template <typename... Args>
barrier_exception(Args&&... args)
: exception(std::forward<Args>(args)...) {}
};
#define TL_BARRIER_EXCEPTION(__fun,__ret) \
barrier_exception(#__fun," returned ", abt_error_get_name(__ret),\
" (", abt_error_get_description(__ret),") in ",__FILE__,":",__LINE__);
#define TL_BARRIER_ASSERT(__call) {\
int __ret = __call; \
if(__ret != ABT_SUCCESS) {\
throw TL_BARRIER_EXCEPTION(__call, __ret);\
}\
}
#define TL_BARRIER_EXCEPTION(__fun, __ret) \
barrier_exception(#__fun, " returned ", abt_error_get_name(__ret), " (", \
abt_error_get_description(__ret), ") in ", __FILE__, \
":", __LINE__);
#define TL_BARRIER_ASSERT(__call) \
{ \
int __ret = __call; \
if(__ret != ABT_SUCCESS) { \
throw TL_BARRIER_EXCEPTION(__call, __ret); \
} \
}
/**
* @brief Wrapper for Argobots' ABT_barrier.
*/
class barrier {
ABT_barrier m_barrier;
public:
public:
/**
* @brief Native handle type (ABT_barrier)
*/
......@@ -62,13 +60,13 @@ class barrier {
/**
* @brief Copy constructor is deleted.
*/
barrier(const barrier& other) = delete;
barrier(const barrier& other) = delete;
/**
* @brief Copy assignment operator is deleted.
*/
barrier& operator=(const barrier& other) = delete;
/**
* @brief Move assignment operator.
*
......@@ -78,11 +76,12 @@ class barrier {
* The right operand will be invalidated.
*/
barrier& operator=(barrier&& other) {
if(this == &other) return *this;
if(this == &other)
return *this;
if(m_barrier != ABT_BARRIER_NULL) {
TL_BARRIER_ASSERT(ABT_barrier_free(&m_barrier));
}
m_barrier = other.m_barrier;
m_barrier = other.m_barrier;
other.m_barrier = ABT_BARRIER_NULL;
return *this;
}
......@@ -93,7 +92,7 @@ class barrier {
*
* @param other barrier object to move from.
*/
barrier(barrier&& other)
barrier(barrier&& other) noexcept
: m_barrier(other.m_barrier) {
other.m_barrier = ABT_BARRIER_NULL;
}
......@@ -101,7 +100,7 @@ class barrier {
/**
* @brief Destructor.
*/
~barrier() {
~barrier() noexcept {
if(m_barrier != ABT_BARRIER_NULL)
ABT_barrier_free(&m_barrier);
}
......@@ -123,9 +122,7 @@ class barrier {
/**
* @brief Waits on the barrier.
*/
void wait() {
TL_BARRIER_ASSERT(ABT_barrier_wait(m_barrier));
}
void wait() { TL_BARRIER_ASSERT(ABT_barrier_wait(m_barrier)); }
/**
* @brief Get the number of waiters that the barrier
......@@ -144,12 +141,10 @@ class barrier {
*
* @return the underlying ABT_barrier handle.
*/
native_handle_type native_handle() const noexcept {
return m_barrier;
}
native_handle_type native_handle() const noexcept { return m_barrier; }
};
}
} // namespace thallium
#undef TL_BARRIER_EXCEPTION
#undef TL_BARRIER_ASSERT
......
/*
* (C) 2017 The University of Chicago
*
* See COPYRIGHT in top-level directory.
*/
#ifndef __THALLIUM_BUFFER_HPP
#define __THALLIUM_BUFFER_HPP
#include <stdlib.h>
#include <string.h>
namespace thallium {
class buffer {
char* m_data = nullptr;
size_t m_size = 0;
size_t m_capacity = 0;
public:
buffer() = default;
buffer(size_t initialSize) {
resize(initialSize);
}
~buffer() {
if(m_data != nullptr)
free(m_data);
}
buffer(const buffer& other) {
if(other.m_data != nullptr) {
m_data = static_cast<char*>(malloc(other.m_size));
m_size = other.m_size;
m_capacity = other.m_size;
memcpy(m_data, other.m_data, m_size);
} else {
m_data = nullptr;
m_size = 0;
m_capacity = 0;
}
}
buffer(buffer&& other) {
m_data = other.m_data;
m_size = other.m_size;
m_capacity = other.m_capacity;
other.m_data = nullptr;
other.m_size = 0;
other.m_capacity = 0;
}
buffer& operator=(const buffer& other) {
if(&other == this) return *this;
if(m_data != nullptr)
free(m_data);
if(other.m_data != nullptr) {
m_data = static_cast<char*>(malloc(other.m_size));
m_size = other.m_size;
m_capacity = other.m_size;
memcpy(m_data, other.m_data, m_size);
} else {
m_data = nullptr;
m_size = 0;
m_capacity = 0;
}
return *this;
}
buffer& operator=(buffer&& other) {
if(&other == this) return *this;
if(m_data != nullptr)
free(m_data);
m_data = other.m_data;
m_size = other.m_size;
m_capacity = other.m_capacity;
other.m_data = nullptr;
other.m_size = 0;
other.m_capacity = 0;
return *this;
}
const char* data() const {
return m_data;
}
char* data() {
return m_data;
}
size_t size() const {
return m_size;
}
size_t capacity() const {
return m_capacity;
}
void resize(size_t newSize) {
if(m_capacity == 0) {
m_data = static_cast<char*>(malloc(newSize));
m_size = newSize;
m_capacity = newSize;
} else if(m_capacity >= newSize) {
m_size = newSize;
} else { // capacity not 0 but too small
while(m_capacity < newSize) m_capacity *= 2;
m_data = static_cast<char*>(realloc(m_data, m_capacity));
m_size = newSize;
}
}
void reserve(size_t newCapacity) {
if(newCapacity <= m_capacity)
return;
m_capacity = newCapacity;
m_data = static_cast<char*>(realloc(m_data, m_capacity));
}
};
}
#endif
This diff is collapsed.
/*
* (C) 2017 The University of Chicago
*
*
* See COPYRIGHT in top-level directory.
*/
#ifndef __THALLIUM_BULK_MODE_HPP
......@@ -20,6 +20,6 @@ enum class bulk_mode : hg_uint32_t {
write_only = HG_BULK_WRITE_ONLY
};
}
} // namespace thallium
#endif
......@@ -9,8 +9,8 @@
#include <abt.h>
#include <mutex>
#include <thallium/mutex.hpp>
#include <thallium/exception.hpp>
#include <thallium/mutex.hpp>
namespace thallium {
......@@ -18,34 +18,32 @@ namespace thallium {
* Exception class thrown by the condition_variable class.
*/
class condition_variable_exception : public exception {
public:
template<typename ... Args>
condition_variable_exception(Args&&... args)
: exception(std::forward<Args>(args)...) {}
public:
template <typename... Args>
condition_variable_exception(Args&&... args)
: exception(std::forward<Args>(args)...) {}
};
#define TL_CV_EXCEPTION(__fun,__ret) \
condition_variable_exception(#__fun," returned ", abt_error_get_name(__ret),\
" (", abt_error_get_description(__ret),") in ",__FILE__,":",__LINE__);
#define TL_CV_ASSERT(__call) {\
int __ret = __call; \
if(__ret != ABT_SUCCESS) {\
throw TL_CV_EXCEPTION(__call, __ret);\
}\
}
#define TL_CV_EXCEPTION(__fun, __ret) \
condition_variable_exception( \
#__fun, " returned ", abt_error_get_name(__ret), " (", \
abt_error_get_description(__ret), ") in ", __FILE__, ":", __LINE__);
#define TL_CV_ASSERT(__call) \
{ \
int __ret = __call; \
if(__ret != ABT_SUCCESS) { \
throw TL_CV_EXCEPTION(__call, __ret); \
} \
}
/**
* @brief Wrapper for Argobots' ABT_cond.
*/
class condition_variable {
ABT_cond m_cond;
public:
public:
/**
* @brief Native handle type.
*/
......@@ -56,21 +54,17 @@ class condition_variable {
*
* @return the underlying ABT_cond handle.
*/
native_handle_type native_handle() const noexcept {
return m_cond;
}
native_handle_type native_handle() const noexcept { return m_cond; }
/**
* @brief Constructor.
*/
condition_variable() {
TL_CV_ASSERT(ABT_cond_create(&m_cond));
}
condition_variable() { TL_CV_ASSERT(ABT_cond_create(&m_cond)); }
/**
* @brief Destructor.
*/
~condition_variable() {
~condition_variable() noexcept {
if(m_cond != ABT_COND_NULL)
ABT_cond_free(&m_cond);
}
......@@ -78,7 +72,7 @@ class condition_variable {
/**
* @brief Copy constructor is deleted.
*/
condition_variable(const condition_variable&) = delete;
condition_variable(const condition_variable&) = delete;
/**
* @brief Copy assignment operator is deleted.
......@@ -92,11 +86,12 @@ class condition_variable {
* leaving the right one invalid.
*/
condition_variable& operator=(condition_variable&& other) {
if(this == &other) return *this;
if(this == &other)
return *this;
if(m_cond != ABT_COND_NULL) {
TL_CV_ASSERT(ABT_cond_free(&m_cond));
}
m_cond = other.m_cond;
m_cond = other.m_cond;
other.m_cond = ABT_COND_NULL;
return *this;
}
......@@ -105,7 +100,7 @@ class condition_variable {
* @brief Move constructor. This function will invalidate
* the passed condition_variable.
*/
condition_variable(condition_variable&& other)
condition_variable(condition_variable&& other) noexcept
: m_cond(other.m_cond) {
other.m_cond = ABT_COND_NULL;
}
......@@ -123,12 +118,12 @@ class condition_variable {
* @brief Wait on a condition variable until a predicate
* becomes true.
*