Skip to content

Commit

Permalink
Merge pull request #80 from DARMA-tasking/feature-issue-56
Browse files Browse the repository at this point in the history
Added support for explicitly specify permissions on AccessHandle objects
  • Loading branch information
David Hollman committed Feb 13, 2018
2 parents 6eb14ad + cc1d8e6 commit 0fcdd7b
Show file tree
Hide file tree
Showing 12 changed files with 596 additions and 7 deletions.
6 changes: 6 additions & 0 deletions src/include/darma/impl/access_handle/access_handle.impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@ AccessHandle<T, Traits>::AccessHandle(
other_private_members_ = copied_from.other_private_members_;
}

// added by gb -- 02-08-2018
if (result.required_permissions) {
this->detail::BasicAccessHandle::_reset_handles();
other_private_members_ = copied_from.other_private_members_;
}

}

//==============================================================================
Expand Down
5 changes: 5 additions & 0 deletions src/include/darma/impl/access_handle/basic_access_handle.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,11 @@ class BasicAccessHandle : public AccessHandleBase {
this->AccessHandleBase::_do_assignment(std::move(other));
}

// added by gb -- 02-08-2018
void _reset_handles() {
this->AccessHandleBase::_reset_handles();
}


// </editor-fold> end assignment operator implementations }}}1
//==============================================================================
Expand Down
45 changes: 40 additions & 5 deletions src/include/darma/impl/access_handle/copy_captured_object.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,14 @@ class CopyCapturedObject {
struct handle_copy_construct_result {
bool did_capture;
bool argument_is_garbage;
bool required_permissions; // added by gb -- 02-08-2018
};

// added by gb -- 02-09-2018
Derived* get_source_object() const {
return const_cast<Derived*>(prev_copied_from_);
}

CopyCapturedObject() = default;
CopyCapturedObject(CopyCapturedObject const&) = default;
CopyCapturedObject(CopyCapturedObject&&) noexcept = default;
Expand All @@ -137,7 +143,20 @@ class CopyCapturedObject {
prev_copied_from_ = &copied_from;
return {
/* did_capture = */ false,
/* argument_is_garbage = */ false
/* argument_is_garbage = */ false,
/* required_permissions = */ false // added by gb -- 02-08-2018
};
}

// added by gb -- 02-08-2018 -- check if permissions were specified
if (running_task->must_specify_permissions &&
CapturedObjectAttorney::captured_as_int(copied_from) == 0
) {
prev_copied_from_ = &copied_from;
return {
/* did_capture = */ false,
/* argument_is_garbage = */ false,
/* required_permissions = */ true // added by gb -- 02-08-2018
};
}

Expand All @@ -151,7 +170,8 @@ class CopyCapturedObject {
// might contain garbage pointers (in the unpack case, at least)
return {
/* did_capture = */ false,
/* argument_is_garbage = */ true
/* argument_is_garbage = */ true,
/* required_permissions = */ false // added by gb -- 02-08-2018
};
} // end if in Lambda serdes mode

Expand All @@ -175,7 +195,8 @@ class CopyCapturedObject {

return {
/* did_capture = */ true,
/* argument_is_garbage = */ false
/* argument_is_garbage = */ false,
/* required_permissions = */ false // added by gb -- 02-08-2018
};

}
Expand All @@ -197,7 +218,20 @@ class CopyCapturedObject {
if(capturing_task == nullptr) {
return {
/* did_capture = */ false,
/* argument_is_garbage = */ false
/* argument_is_garbage = */ false,
/* required_permissions = */ false // added by gb -- 02-08-2018
};
}

// added by gb -- 02-08-2018 -- check if permissions were specified
if (running_task->must_specify_permissions &&
CapturedObjectAttorney::captured_as_int(copied_from) == 0
) {

return {
/* did_capture = */ false,
/* argument_is_garbage = */ false,
/* required_permissions = */ true // added by gb -- 02-08-2018
};
}

Expand All @@ -209,7 +243,8 @@ class CopyCapturedObject {

return {
/* did_capture = */ true,
/* argument_is_garbage = */ false
/* argument_is_garbage = */ false,
/* required_permissions = */ false // added by gb -- 02-08-2018
};

}
Expand Down
6 changes: 6 additions & 0 deletions src/include/darma/impl/access_handle_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,12 @@ class AccessHandleBase
current_use_base_ = other.current_use_base_;
}

// added by gb -- 02-08-2018
void _reset_handles() {
var_handle_base_ = nullptr;
current_use_base_ = nullptr;
}


// </editor-fold> end assignment operator implementation }}}2
//------------------------------------------------------------------------------
Expand Down
104 changes: 104 additions & 0 deletions src/include/darma/impl/capture/functor_traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,66 @@ namespace darma_runtime {

namespace detail {

struct variadic_tag_has_downgrades_permissions { };
struct variadic_tag_has_required_permissions { };
struct variadic_tag_permissions_not_specified { };

namespace _permissions_traits_impl {

// Utility metafunctions
template <typename T> using vvoid_t = void;

template <typename T> struct _is_member_callable : std::false_type {typedef void type;};
template <typename Ret, typename... Args> struct _is_member_callable<Ret(*)(Args...)> : std::true_type { typedef Ret(*type)(Args...); };

template <typename FirstArg, typename... LastArgs> struct _is_arg_by_value {
static constexpr bool value =
(not std::is_reference<FirstArg>::value) and
_is_arg_by_value<LastArgs...>::value;
};

template <typename Arg> struct _is_arg_by_value<Arg> {
static constexpr bool value = not std::is_reference<Arg>::value;
};

// Check whether a method can be invoked with the given call arguments
template <typename T, typename... Args>
using is_method_callable_with_args_archetype = decltype(std::declval<T>()(std::declval<Args>()...));

// Detect presence of static permissions_downgrades method in class
template <typename T, typename> struct has_permissions_downgrades {
typedef void type;
static constexpr bool value = false;
};

template <typename T> struct has_permissions_downgrades<T, vvoid_t<decltype(&T::permissions_downgrades)>> {
typedef typename _is_member_callable<decltype(&T::permissions_downgrades)>::type type;
static constexpr bool value = _is_member_callable<decltype(&T::permissions_downgrades)>::value;
};

// Detect presence of static required_permissions method in class
template <typename T, typename> struct has_required_permissions {
typedef void type;
static constexpr bool value = false;
};

template <typename T> struct has_required_permissions<T, vvoid_t<decltype(&T::required_permissions)>> {
typedef typename _is_member_callable<decltype(&T::required_permissions)>::type type;
static constexpr bool value = _is_member_callable<decltype(&T::required_permissions)>::value;
};

// All formal arguments to permissions methods must be passed by value
template <typename T> struct arguments_by_value {
static constexpr bool value = _is_arg_by_value<T>::value;
};

template <typename Ret, typename... Args> struct arguments_by_value<Ret(*)(Args...)> {
static constexpr bool value = _is_arg_by_value<void, Args...>::value;
};

} // end namespace _permissions_traits_impl


////////////////////////////////////////////////////////////////////////////////

// <editor-fold desc="FunctorWrapper traits">
Expand Down Expand Up @@ -171,6 +231,50 @@ template <
>
struct functor_call_traits {

public:

typedef typename _permissions_traits_impl::has_permissions_downgrades<Functor, void>::type ftype_perm_down;
static constexpr bool has_static_permissions_downgrades = _permissions_traits_impl::has_permissions_downgrades<Functor, void>::value;
static constexpr bool static_permissions_downgrades_is_callable_with_args =
tinympl::is_detected<_permissions_traits_impl::is_method_callable_with_args_archetype, ftype_perm_down, CallArgs...>::value;

typedef typename _permissions_traits_impl::has_required_permissions<Functor, void>::type ftype_reqr_perm;
static constexpr bool has_static_required_permissions = _permissions_traits_impl::has_required_permissions<Functor, void>::value;
static constexpr bool static_required_permissions_is_callable_with_args =
tinympl::is_detected<_permissions_traits_impl::is_method_callable_with_args_archetype, ftype_reqr_perm, CallArgs...>::value;

// permissions_downgrades and required_permissions should be mutually exclusive
// static_assert(not (has_static_permissions_downgrades and has_static_required_permissions),
// "Error. Static methods required_permissions and permissions_downgrades in a functor must be mutually exclusive."
// );

// if required_permissions method exists, it should be callable with the call arguments passed to the functor
// static_assert(static_required_permissions_is_callable_with_args or (not has_static_required_permissions),
// "Error. Static method required_permissions is not callable with call arguments passed to functor"
// );

// same holds true for permissions_downgrades
// static_assert(static_permissions_downgrades_is_callable_with_args or (not has_static_permissions_downgrades),
// "Error. Static method permissions_downgrades is not callable with call arguments passed to functor"
// );

static constexpr bool permissions_downgrades_arguments_by_value = _permissions_traits_impl::arguments_by_value<ftype_perm_down>::value;
static constexpr bool required_permissions_arguments_by_value = _permissions_traits_impl::arguments_by_value<ftype_reqr_perm>::value;

// currently, non-elementary call arguments should be passed by reference to permissions methods
// static_assert(permissions_downgrades_arguments_by_reference and required_permissions_arguments_by_reference,
// "Error. Non-elementary arguments of permissions method should be passed by reference"
// );

typedef typename tinympl::select_first_t<
tinympl::bool_constant<permissions_downgrades_arguments_by_value and (not std::is_void<ftype_perm_down>::value)>,
/* => */ variadic_tag_has_downgrades_permissions,
tinympl::bool_constant<required_permissions_arguments_by_value and (not std::is_void<ftype_reqr_perm>::value)>,
/* => */ variadic_tag_has_required_permissions,
std::true_type,
/* => */ variadic_tag_permissions_not_specified
> dispatch_tag;

public:

template <size_t N>
Expand Down
81 changes: 81 additions & 0 deletions src/include/darma/impl/create_work/capture_permissions.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ struct PermissionsPair {

struct DeferredPermissionsModificationsBase {
virtual void do_permissions_modifications() = 0;
virtual void do_source_permissions_modifications() = 0; // added by gb -- 02-09-2018
virtual ~DeferredPermissionsModificationsBase() = default;
};

Expand Down Expand Up @@ -182,6 +183,46 @@ struct DeferredPermissionsModifications : DeferredPermissionsModificationsBase
return 0;
}

// added by gb -- 02-09-2018
template <
typename CapturedObjectBaseT,
typename CallableT
>
int
apply_source_permissions_modifications(
CapturedObjectBaseT&& obj,
CallableT const& callable,
std::enable_if_t<
std::is_base_of<CapturedObjectBase, std::decay_t<CapturedObjectBaseT>>::value,
utility::_not_a_type
> /*unused*/ = { }
) {
callable(obj.get_source_access_handle());
return 0;
}

// added by gb -- 02-09-2018
template <
typename DeferredPermissionsModificationsT,
typename CallableT
>
int
apply_source_permissions_modifications(
DeferredPermissionsModificationsT&& obj,
CallableT const& callable,
std::enable_if_t<
std::is_base_of<
DeferredPermissionsModificationsBase,
std::decay_t<DeferredPermissionsModificationsT>
>::value,
utility::_not_a_type
> /*unused*/ = { }
) {
obj.apply_source_permissions_modifications(callable);
// Don't forget to invoke the nested modifications as well:
obj.do_permissions_modifications();
return 0;
}

private:

Expand All @@ -205,6 +246,23 @@ struct DeferredPermissionsModifications : DeferredPermissionsModificationsBase

}

// added by gb -- 02-09-2018
template <
typename CallableT,
size_t... Idxs
>
void _apply_source_permissions_modifications_impl(
std::integer_sequence<size_t, Idxs...>,
CallableT const& callable
) {
std::make_tuple( // fold emulation
apply_source_permissions_modifications(
std::get<Idxs>(arg_refs_tuple_),
callable
)...
);
}

public:

DeferredPermissionsModifications(DeferredPermissionsModifications const&) = delete;
Expand All @@ -223,6 +281,19 @@ struct DeferredPermissionsModifications : DeferredPermissionsModificationsBase
);
}

// added by gb -- 02-09-2018
template <
typename CallableT
>
void apply_source_permissions_modifications(
CallableT const& callable
) {
_apply_source_permissions_modifications_impl(
std::index_sequence_for<Args...>{},
callable
);
}

template <typename CallableDeduced, typename... ArgsDeduced>
DeferredPermissionsModifications(
utility::variadic_constructor_tag_t /*unused*/, // prevent generation of move and copy ctors via this template
Expand All @@ -236,6 +307,10 @@ struct DeferredPermissionsModifications : DeferredPermissionsModificationsBase
apply_permissions_modifications(callable_);
}

// added by gb -- 02-09-2018 -- modify permissions on source ah
void do_source_permissions_modifications() override {
apply_source_permissions_modifications(callable_);
}
};

template <typename Callable, typename... PassThroughArgs>
Expand All @@ -260,6 +335,12 @@ struct CapturedObjectAttorney {
return obj.captured_as.info;
}

// added by gb -- 02-09-2018
static CapturedObjectBase::captured_as_info_as_int_t
captured_as_int(CapturedObjectBase const& obj) {
return obj.captured_as.as_int;
}

static void
clear_capture_state(CapturedObjectBase const& obj) {
obj.clear_capture_state();
Expand Down
Loading

0 comments on commit 0fcdd7b

Please sign in to comment.