diff --git a/NAMESPACE b/NAMESPACE index 0a50a48c..f70b3089 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -37,6 +37,8 @@ S3method(get_queue_size,wrap) S3method(get_queue_size_selected,simmer) S3method(get_resources,simmer) S3method(get_resources,wrap) +S3method(get_seized,simmer) +S3method(get_seized_selected,simmer) S3method(get_selected,simmer) S3method(get_server_count,simmer) S3method(get_server_count,wrap) @@ -54,7 +56,9 @@ S3method(now,wrap) S3method(peek,simmer) S3method(peek,wrap) S3method(release,trajectory) +S3method(release_all,trajectory) S3method(release_selected,trajectory) +S3method(release_selected_all,trajectory) S3method(renege_abort,trajectory) S3method(renege_if,trajectory) S3method(renege_in,trajectory) @@ -112,6 +116,8 @@ export(get_queue_count_selected) export(get_queue_size) export(get_queue_size_selected) export(get_resources) +export(get_seized) +export(get_seized_selected) export(get_selected) export(get_server_count) export(get_server_count_selected) @@ -128,7 +134,9 @@ export(monitor_mem) export(now) export(peek) export(release) +export(release_all) export(release_selected) +export(release_selected_all) export(renege_abort) export(renege_if) export(renege_in) diff --git a/NEWS.md b/NEWS.md index 05a34b02..5d19e0c6 100644 --- a/NEWS.md +++ b/NEWS.md @@ -6,12 +6,17 @@ arrivals, i.e., those dropped from a resource (due to preemption, resource shrinkage or a rejected `seize`) or those that `leave` a trajectory (#178 addressing #177). +- New `release_all()` and `release_selected_all()` activities automatically + retrieve the amount of resources seized and release it (#180 addressing #25). +- New `get_seized()` and `get_seized_selected()` getters allow an arrival to + retrieve the amount of resources seized (#180 addressing #179). ## Minor changes and fixes: - Fix performance issues in data sources (#176). - Update CITATION. - Fix monitored activity for preempted arrivals (as part of #178). +- Fix seizes/releases with a null amount (as part of #180). # simmer 4.1.0 diff --git a/R/RcppExports.R b/R/RcppExports.R index 44d7da63..d70aa936 100644 --- a/R/RcppExports.R +++ b/R/RcppExports.R @@ -25,6 +25,14 @@ Release__new_func <- function(resource, amount) { .Call(`_simmer_Release__new_func`, resource, amount) } +ReleaseAll__new <- function(resource) { + .Call(`_simmer_ReleaseAll__new`, resource) +} + +ReleaseAll__new_void <- function() { + .Call(`_simmer_ReleaseAll__new_void`) +} + ReleaseSelected__new <- function(id, amount) { .Call(`_simmer_ReleaseSelected__new`, id, amount) } @@ -33,6 +41,10 @@ ReleaseSelected__new_func <- function(id, amount) { .Call(`_simmer_ReleaseSelected__new_func`, id, amount) } +ReleaseSelectedAll__new <- function(id) { + .Call(`_simmer_ReleaseSelectedAll__new`, id) +} + SetCapacity__new <- function(resource, value, mod) { .Call(`_simmer_SetCapacity__new`, resource, value, mod) } @@ -365,6 +377,14 @@ get_queue_count_selected_ <- function(sim_, id) { .Call(`_simmer_get_queue_count_selected_`, sim_, id) } +get_seized_ <- function(sim_, names) { + .Call(`_simmer_get_seized_`, sim_, names) +} + +get_seized_selected_ <- function(sim_, id) { + .Call(`_simmer_get_seized_selected_`, sim_, id) +} + get_selected_ <- function(sim_, id) { .Call(`_simmer_get_selected_`, sim_, id) } diff --git a/R/simmer-class.R b/R/simmer-class.R index c4f01085..dc55ef89 100644 --- a/R/simmer-class.R +++ b/R/simmer-class.R @@ -250,7 +250,7 @@ Simmer <- R6Class("simmer", get_prioritization = function() get_prioritization_(private$sim_obj), get_capacity = function(resources, id=0) { - check_args(resources=c("string vector", "NULL"), id="numeric") + check_args(resources=c("string vector", "NULL"), id="number") ret <- switch( binarise(is.null(resources)), get_capacity_(private$sim_obj, resources), @@ -260,7 +260,7 @@ Simmer <- R6Class("simmer", }, get_queue_size = function(resources, id=0) { - check_args(resources=c("string vector", "NULL"), id="numeric") + check_args(resources=c("string vector", "NULL"), id="number") ret <- switch( binarise(is.null(resources)), get_queue_size_(private$sim_obj, resources), @@ -270,7 +270,7 @@ Simmer <- R6Class("simmer", }, get_server_count = function(resources, id=0) { - check_args(resources=c("string vector", "NULL"), id="numeric") + check_args(resources=c("string vector", "NULL"), id="number") switch( binarise(is.null(resources)), get_server_count_(private$sim_obj, resources), @@ -279,7 +279,7 @@ Simmer <- R6Class("simmer", }, get_queue_count = function(resources, id=0) { - check_args(resources=c("string vector", "NULL"), id="numeric") + check_args(resources=c("string vector", "NULL"), id="number") ret <- switch( binarise(is.null(resources)), get_queue_count_(private$sim_obj, resources), @@ -287,8 +287,17 @@ Simmer <- R6Class("simmer", ) }, + get_seized = function(resources, id=0) { + check_args(resources=c("string vector", "NULL"), id="number") + ret <- switch( + binarise(is.null(resources)), + get_seized_(private$sim_obj, resources), + get_seized_selected_(private$sim_obj, id) + ) + }, + get_selected = function(id=0) { - check_args(id="numeric") + check_args(id="number") get_selected_(private$sim_obj, id) }, diff --git a/R/simmer-methods.R b/R/simmer-methods.R index dc06cad8..6f6380c7 100644 --- a/R/simmer-methods.R +++ b/R/simmer-methods.R @@ -40,13 +40,14 @@ #' \code{\link{get_server_count}}, \code{\link{get_queue_count}}, #' \code{\link{get_capacity_selected}}, \code{\link{get_queue_size_selected}}, #' \code{\link{get_server_count_selected}}, \code{\link{get_queue_count_selected}}, +#' \code{\link{get_seized}}, \code{\link{get_seized_selected}}, #' \code{\link{get_selected}} #' #' \item Sources: \code{\link{add_generator}}, \code{\link{add_dataframe}}, #' \code{\link{get_sources}}, \code{\link{get_n_generated}}, #' \code{\link{get_trajectory}} #' -#' \item Globals: \code{\link{add_global}}, \code{\link{get_global}}. +#' \item Globals: \code{\link{add_global}}, \code{\link{get_global}} #' #' \item Data retrieval: \code{\link{get_mon_arrivals}}, #' \code{\link{get_mon_attributes}}, \code{\link{get_mon_resources}} @@ -436,12 +437,12 @@ get_prioritization.simmer <- function(.env) .env$get_prioritization() #' Get Resource Parameters #' -#' Getters for resources: server capacity/count and queue size/count. +#' Getters for resources: server capacity/count and queue size/count, seized +#' amount and selected resources. #' #' @inheritParams reset +#' @inheritParams select #' @param resources one or more resource names. -#' @param id selection identifier (a negative number causes the function to -#' return the required parameter for all the selected resources). #' #' @return Return a vector (character for \code{get_selected}, numeric for the #' rest of them). @@ -502,6 +503,20 @@ get_queue_count_selected <- function(.env, id=0) UseMethod("get_queue_count_sele #' @export get_queue_count_selected.simmer <- function(.env, id=0) .env$get_queue_count(NULL, id) +#' @rdname get_capacity +#' @export +get_seized <- function(.env, resources) UseMethod("get_seized") + +#' @export +get_seized.simmer <- function(.env, resources) .env$get_seized(resources) + +#' @rdname get_capacity +#' @export +get_seized_selected <- function(.env, id=0) UseMethod("get_seized_selected") + +#' @export +get_seized_selected.simmer <- function(.env, id=0) .env$get_seized(NULL, id) + #' @rdname get_capacity #' @export get_selected <- function(.env, id=0) UseMethod("get_selected") diff --git a/R/trajectory-activities.R b/R/trajectory-activities.R index 46025ae5..ddff8a1d 100644 --- a/R/trajectory-activities.R +++ b/R/trajectory-activities.R @@ -73,6 +73,20 @@ release_selected <- function(.trj, amount=1, id=0) UseMethod("release_selected") #' @export release_selected.trajectory <- function(.trj, amount=1, id=0) .trj$release(NA, amount, id) +#' @rdname seize +#' @export +release_all <- function(.trj, resource) UseMethod("release_all") + +#' @export +release_all.trajectory <- function(.trj, resource) .trj$release(resource, NA) + +#' @rdname seize +#' @export +release_selected_all <- function(.trj, id=0) UseMethod("release_selected_all") + +#' @export +release_selected_all.trajectory <- function(.trj, id=0) .trj$release(NA, NA, id) + #' Set Resource Parameters #' #' Activities for modifying a resource's server capacity or queue size, by name diff --git a/R/trajectory-class.R b/R/trajectory-class.R index 3d35eae7..18b4c730 100644 --- a/R/trajectory-class.R +++ b/R/trajectory-class.R @@ -125,11 +125,19 @@ Trajectory <- R6Class("trajectory", }, release = function(resource, amount=1, id=0) { - check_args(resource=c("string", "NA"), amount=c("number", "function"), id="number") + if (missing(resource)) + return(private$add_activity(ReleaseAll__new_void())) + check_args( + resource = c("string", "NA"), + amount = c("number", "function", "NA"), + id = "number" + ) switch( - binarise(is.na(resource), is.function(amount)), + binarise(is.na(resource), is.na(amount), is.function(amount)), private$add_activity(Release__new(resource, amount)), private$add_activity(ReleaseSelected__new(id, amount)), + private$add_activity(ReleaseAll__new(resource)), + private$add_activity(ReleaseSelectedAll__new(id)), private$add_activity(Release__new_func(resource, amount)), private$add_activity(ReleaseSelected__new_func(id, amount)) ) diff --git a/R/trajectory-methods.R b/R/trajectory-methods.R index 6361b568..e3356a70 100644 --- a/R/trajectory-methods.R +++ b/R/trajectory-methods.R @@ -40,9 +40,10 @@ #' \code{\link{set_prioritization}} #' #' \item Interaction with resources: \code{\link{select}}, \code{\link{seize}}, -#' \code{\link{release}}, \code{\link{seize_selected}}, \code{\link{release_selected}}, -#' \code{\link{set_capacity}}, \code{\link{set_queue_size}}, \code{\link{set_capacity_selected}}, -#' \code{\link{set_queue_size_selected}} +#' \code{\link{release}}, \code{\link{release_all}}, \code{\link{seize_selected}}, +#' \code{\link{release_selected}}, \code{\link{release_selected_all}}, +#' \code{\link{set_capacity}}, \code{\link{set_queue_size}}, +#' \code{\link{set_capacity_selected}}, \code{\link{set_queue_size_selected}} #' #' \item Interaction with generators: \code{\link{activate}}, \code{\link{deactivate}}, #' \code{\link{set_trajectory}}, \code{\link{set_source}} @@ -56,8 +57,8 @@ #' \item Asynchronous programming: \code{\link{send}}, \code{\link{trap}}, #' \code{\link{untrap}}, \code{\link{wait}} #' -#' \item Reneging: \code{\link{leave}}, \code{\link{renege_in}}, \code{\link{renege_if}}, -#' \code{\link{renege_abort}} +#' \item Reneging: \code{\link{leave}}, \code{\link{handle_unfinished}}, +#' \code{\link{renege_in}}, \code{\link{renege_if}}, \code{\link{renege_abort}} #' #' } #' diff --git a/inst/include/simmer/activity/resource.h b/inst/include/simmer/activity/resource.h index 86f0a134..8d2d69ad 100644 --- a/inst/include/simmer/activity/resource.h +++ b/inst/include/simmer/activity/resource.h @@ -41,7 +41,7 @@ namespace simmer { Seize(int id, const T& amount, const VEC& cont, const VEC& trj, unsigned short mask) : Fork("Seize", cont, trj), - internal::ResGetter("Seize", "[]", id), amount(amount), mask(mask) {} + internal::ResGetter("Seize", id), amount(amount), mask(mask) {} void print(unsigned int indent = 0, bool verbose = false, bool brief = false) { Activity::print(indent, verbose, brief); @@ -50,8 +50,8 @@ namespace simmer { } double run(Arrival* arrival) { - return select_path( - arrival, get_resource(arrival)->seize(arrival, std::abs(get(amount, arrival)))); + return select_path(arrival, get_resource(arrival)-> + seize(arrival, std::abs(get(amount, arrival)))); } protected: @@ -86,25 +86,41 @@ namespace simmer { public: CLONEABLE(Release) - Release(const std::string& resource, const T& amount) + Release() + : Activity("Release", PRIORITY_RELEASE), + internal::ResGetter("Release"), amount(NONE) {} + + Release(const std::string& resource, const OPT& amount = NONE) : Activity("Release", PRIORITY_RELEASE), internal::ResGetter("Release", resource), amount(amount) {} - Release(int id, const T& amount) + Release(int id, const OPT& amount = NONE) : Activity("Release", PRIORITY_RELEASE), - internal::ResGetter("Release", "[]", id), amount(amount) {} + internal::ResGetter("Release", id), amount(amount) {} void print(unsigned int indent = 0, bool verbose = false, bool brief = false) { Activity::print(indent, verbose, brief); - internal::print(brief, true, ARG(resource), ARG(amount)); + if (amount) + internal::print(brief, true, ARG(resource), "amount: ", *amount); + else internal::print(brief, true, ARG(resource), "amount: ", "all"); } double run(Arrival* arrival) { - return get_resource(arrival)->release(arrival, std::abs(get(amount, arrival))); + if (Resource* res = get_resource(arrival)) { + if (amount) + return res->release(arrival, std::abs(get(*amount, arrival))); + return res->release(arrival, res->get_seized(arrival)); + } + + foreach_ (const std::string& resource, arrival->sim->get_resources()) { + Resource* res = arrival->sim->get_resource(resource); + res->release(arrival, res->get_seized(arrival)); + } + return 0; } protected: - T amount; + OPT amount; }; /** @@ -120,7 +136,7 @@ namespace simmer { value(value), mod(mod), op(internal::get_op(mod)) {} SetCapacity(int id, const T& value, char mod='N') - : Activity("SetCapacity"), internal::ResGetter("SetCapacity", "[]", id), + : Activity("SetCapacity"), internal::ResGetter("SetCapacity", id), value(value), mod(mod), op(internal::get_op(mod)) {} void print(unsigned int indent = 0, bool verbose = false, bool brief = false) { @@ -161,7 +177,7 @@ namespace simmer { value(value), mod(mod), op(internal::get_op(mod)) {} SetQueue(int id, const T& value, char mod='N') - : Activity("SetQueue"), internal::ResGetter("SetQueue", "[]", id), + : Activity("SetQueue"), internal::ResGetter("SetQueue", id), value(value), mod(mod), op(internal::get_op(mod)) {} void print(unsigned int indent = 0, bool verbose = false, bool brief = false) { diff --git a/inst/include/simmer/activity/resource_internal.h b/inst/include/simmer/activity/resource_internal.h index 0b1baac3..1aa1206b 100644 --- a/inst/include/simmer/activity/resource_internal.h +++ b/inst/include/simmer/activity/resource_internal.h @@ -29,8 +29,15 @@ namespace simmer { namespace internal { public: BASE_CLONEABLE(ResGetter) - ResGetter(const std::string& activity, const std::string& resource, int id = -1) - : resource(resource), id(id), activity(activity) {} + ResGetter(const std::string& activity) + : resource(MakeString() << "[all]"), id(-2), activity(activity) {} + + ResGetter(const std::string& activity, const std::string& resource) + : resource(resource), id(-1), activity(activity) {} + + ResGetter(const std::string& activity, int id) + : resource(MakeString() << "[" << id << "]"), + id(std::abs(id)), activity(activity) {} protected: std::string resource; @@ -38,7 +45,8 @@ namespace simmer { namespace internal { Resource* get_resource(Arrival* arrival) const { Resource* selected = NULL; - if (id < 0) + if (id == -2) return selected; + if (id == -1) selected = arrival->sim->get_resource(resource); else selected = arrival->get_resource_selected(id); if (!selected) Rcpp::stop("no resource selected"); diff --git a/inst/include/simmer/resource.h b/inst/include/simmer/resource.h index 9a71a891..5036d098 100644 --- a/inst/include/simmer/resource.h +++ b/inst/include/simmer/resource.h @@ -59,6 +59,8 @@ namespace simmer { * @return SUCCESS, ENQUEUE, REJECT */ int seize(Arrival* arrival, int amount) { + if (!amount) return SUCCESS; + int status; // serve now if (first_in_line(arrival->order.get_priority()) && @@ -92,6 +94,8 @@ namespace simmer { * @return SUCCESS */ int release(Arrival* arrival, int amount) { + if (!amount) return SUCCESS; + remove_from_server(arrival, amount); arrival->unregister_entity(this); @@ -158,6 +162,8 @@ namespace simmer { int get_server_count() const { return server_count; } int get_queue_count() const { return queue_count; } + virtual int get_seized(Arrival* arrival) const = 0; + protected: int capacity; int queue_size; diff --git a/inst/include/simmer/resource/priority.h b/inst/include/simmer/resource/priority.h index 9b8aab2a..2b9fd07e 100644 --- a/inst/include/simmer/resource/priority.h +++ b/inst/include/simmer/resource/priority.h @@ -49,6 +49,13 @@ namespace simmer { server_map.clear(); } + int get_seized(Arrival* arrival) const { + typename ServerMap::const_iterator search = server_map.find(arrival); + if (search != server_map.end()) + return search->second->amount; + return 0; + } + protected: T server; ServerMap server_map; diff --git a/inst/include/simmer/simulator.h b/inst/include/simmer/simulator.h index e9b4848f..bf295c27 100644 --- a/inst/include/simmer/simulator.h +++ b/inst/include/simmer/simulator.h @@ -154,6 +154,13 @@ namespace simmer { Arrival* get_running_arrival() const; void record_ongoing(bool per_resource) const; + VEC get_resources() const { + VEC out; + foreach_ (const EntMap::value_type& itr, resource_map) + out.push_back(itr.first); + return out; + } + Batched** get_batch(Activity* ptr, const std::string& id) { if (id.size()) { if (namedb_map.find(id) == namedb_map.end()) diff --git a/man/get_capacity.Rd b/man/get_capacity.Rd index 7db2b199..17e75380 100644 --- a/man/get_capacity.Rd +++ b/man/get_capacity.Rd @@ -9,6 +9,8 @@ \alias{get_server_count_selected} \alias{get_queue_count} \alias{get_queue_count_selected} +\alias{get_seized} +\alias{get_seized_selected} \alias{get_selected} \title{Get Resource Parameters} \usage{ @@ -28,6 +30,10 @@ get_queue_count(.env, resources) get_queue_count_selected(.env, id = 0) +get_seized(.env, resources) + +get_seized_selected(.env, id = 0) + get_selected(.env, id = 0) } \arguments{ @@ -35,15 +41,15 @@ get_selected(.env, id = 0) \item{resources}{one or more resource names.} -\item{id}{selection identifier (a negative number causes the function to -return the required parameter for all the selected resources).} +\item{id}{selection identifier for nested usage.} } \value{ Return a vector (character for \code{get_selected}, numeric for the rest of them). } \description{ -Getters for resources: server capacity/count and queue size/count. +Getters for resources: server capacity/count and queue size/count, seized +amount and selected resources. } \seealso{ \code{\link{get_resources}}, \code{\link{set_capacity}}, diff --git a/man/seize.Rd b/man/seize.Rd index 5289f56d..7368dc91 100644 --- a/man/seize.Rd +++ b/man/seize.Rd @@ -5,6 +5,8 @@ \alias{seize_selected} \alias{release} \alias{release_selected} +\alias{release_all} +\alias{release_selected_all} \title{Seize/Release Resources} \usage{ seize(.trj, resource, amount = 1, continue = NULL, post.seize = NULL, @@ -16,6 +18,10 @@ seize_selected(.trj, amount = 1, id = 0, continue = NULL, release(.trj, resource, amount = 1) release_selected(.trj, amount = 1, id = 0) + +release_all(.trj, resource) + +release_selected_all(.trj, id = 0) } \arguments{ \item{.trj}{the trajectory object.} diff --git a/man/simmer.Rd b/man/simmer.Rd index 06bdd1db..30afa4aa 100644 --- a/man/simmer.Rd +++ b/man/simmer.Rd @@ -54,13 +54,14 @@ Available methods by category: \code{\link{get_server_count}}, \code{\link{get_queue_count}}, \code{\link{get_capacity_selected}}, \code{\link{get_queue_size_selected}}, \code{\link{get_server_count_selected}}, \code{\link{get_queue_count_selected}}, +\code{\link{get_seized}}, \code{\link{get_seized_selected}}, \code{\link{get_selected}} \item Sources: \code{\link{add_generator}}, \code{\link{add_dataframe}}, \code{\link{get_sources}}, \code{\link{get_n_generated}}, \code{\link{get_trajectory}} -\item Globals: \code{\link{add_global}}, \code{\link{get_global}}. +\item Globals: \code{\link{add_global}}, \code{\link{get_global}} \item Data retrieval: \code{\link{get_mon_arrivals}}, \code{\link{get_mon_attributes}}, \code{\link{get_mon_resources}} diff --git a/man/trajectory.Rd b/man/trajectory.Rd index 1fa70799..6f9e84c2 100644 --- a/man/trajectory.Rd +++ b/man/trajectory.Rd @@ -52,9 +52,10 @@ Available activities by category: \code{\link{set_prioritization}} \item Interaction with resources: \code{\link{select}}, \code{\link{seize}}, -\code{\link{release}}, \code{\link{seize_selected}}, \code{\link{release_selected}}, -\code{\link{set_capacity}}, \code{\link{set_queue_size}}, \code{\link{set_capacity_selected}}, -\code{\link{set_queue_size_selected}} +\code{\link{release}}, \code{\link{release_all}}, \code{\link{seize_selected}}, +\code{\link{release_selected}}, \code{\link{release_selected_all}}, +\code{\link{set_capacity}}, \code{\link{set_queue_size}}, +\code{\link{set_capacity_selected}}, \code{\link{set_queue_size_selected}} \item Interaction with generators: \code{\link{activate}}, \code{\link{deactivate}}, \code{\link{set_trajectory}}, \code{\link{set_source}} @@ -68,8 +69,8 @@ Available activities by category: \item Asynchronous programming: \code{\link{send}}, \code{\link{trap}}, \code{\link{untrap}}, \code{\link{wait}} -\item Reneging: \code{\link{leave}}, \code{\link{renege_in}}, \code{\link{renege_if}}, -\code{\link{renege_abort}} +\item Reneging: \code{\link{leave}}, \code{\link{handle_unfinished}}, +\code{\link{renege_in}}, \code{\link{renege_if}}, \code{\link{renege_abort}} } diff --git a/src/RcppExports.cpp b/src/RcppExports.cpp index 073d87c9..b136cfc7 100644 --- a/src/RcppExports.cpp +++ b/src/RcppExports.cpp @@ -90,6 +90,27 @@ BEGIN_RCPP return rcpp_result_gen; END_RCPP } +// ReleaseAll__new +SEXP ReleaseAll__new(const std::string& resource); +RcppExport SEXP _simmer_ReleaseAll__new(SEXP resourceSEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< const std::string& >::type resource(resourceSEXP); + rcpp_result_gen = Rcpp::wrap(ReleaseAll__new(resource)); + return rcpp_result_gen; +END_RCPP +} +// ReleaseAll__new_void +SEXP ReleaseAll__new_void(); +RcppExport SEXP _simmer_ReleaseAll__new_void() { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + rcpp_result_gen = Rcpp::wrap(ReleaseAll__new_void()); + return rcpp_result_gen; +END_RCPP +} // ReleaseSelected__new SEXP ReleaseSelected__new(int id, int amount); RcppExport SEXP _simmer_ReleaseSelected__new(SEXP idSEXP, SEXP amountSEXP) { @@ -114,6 +135,17 @@ BEGIN_RCPP return rcpp_result_gen; END_RCPP } +// ReleaseSelectedAll__new +SEXP ReleaseSelectedAll__new(int id); +RcppExport SEXP _simmer_ReleaseSelectedAll__new(SEXP idSEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< int >::type id(idSEXP); + rcpp_result_gen = Rcpp::wrap(ReleaseSelectedAll__new(id)); + return rcpp_result_gen; +END_RCPP +} // SetCapacity__new SEXP SetCapacity__new(const std::string& resource, double value, char mod); RcppExport SEXP _simmer_SetCapacity__new(SEXP resourceSEXP, SEXP valueSEXP, SEXP modSEXP) { @@ -1121,6 +1153,30 @@ BEGIN_RCPP return rcpp_result_gen; END_RCPP } +// get_seized_ +std::vector get_seized_(SEXP sim_, const std::vector& names); +RcppExport SEXP _simmer_get_seized_(SEXP sim_SEXP, SEXP namesSEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< SEXP >::type sim_(sim_SEXP); + Rcpp::traits::input_parameter< const std::vector& >::type names(namesSEXP); + rcpp_result_gen = Rcpp::wrap(get_seized_(sim_, names)); + return rcpp_result_gen; +END_RCPP +} +// get_seized_selected_ +std::vector get_seized_selected_(SEXP sim_, int id); +RcppExport SEXP _simmer_get_seized_selected_(SEXP sim_SEXP, SEXP idSEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< SEXP >::type sim_(sim_SEXP); + Rcpp::traits::input_parameter< int >::type id(idSEXP); + rcpp_result_gen = Rcpp::wrap(get_seized_selected_(sim_, id)); + return rcpp_result_gen; +END_RCPP +} // get_selected_ std::vector get_selected_(SEXP sim_, int id); RcppExport SEXP _simmer_get_selected_(SEXP sim_SEXP, SEXP idSEXP) { @@ -1311,8 +1367,11 @@ static const R_CallMethodDef CallEntries[] = { {"_simmer_SeizeSelected__new_func", (DL_FUNC) &_simmer_SeizeSelected__new_func, 5}, {"_simmer_Release__new", (DL_FUNC) &_simmer_Release__new, 2}, {"_simmer_Release__new_func", (DL_FUNC) &_simmer_Release__new_func, 2}, + {"_simmer_ReleaseAll__new", (DL_FUNC) &_simmer_ReleaseAll__new, 1}, + {"_simmer_ReleaseAll__new_void", (DL_FUNC) &_simmer_ReleaseAll__new_void, 0}, {"_simmer_ReleaseSelected__new", (DL_FUNC) &_simmer_ReleaseSelected__new, 2}, {"_simmer_ReleaseSelected__new_func", (DL_FUNC) &_simmer_ReleaseSelected__new_func, 2}, + {"_simmer_ReleaseSelectedAll__new", (DL_FUNC) &_simmer_ReleaseSelectedAll__new, 1}, {"_simmer_SetCapacity__new", (DL_FUNC) &_simmer_SetCapacity__new, 3}, {"_simmer_SetCapacity__new_func", (DL_FUNC) &_simmer_SetCapacity__new_func, 3}, {"_simmer_SetCapacitySelected__new", (DL_FUNC) &_simmer_SetCapacitySelected__new, 3}, @@ -1396,6 +1455,8 @@ static const R_CallMethodDef CallEntries[] = { {"_simmer_get_server_count_selected_", (DL_FUNC) &_simmer_get_server_count_selected_, 2}, {"_simmer_get_queue_count_", (DL_FUNC) &_simmer_get_queue_count_, 2}, {"_simmer_get_queue_count_selected_", (DL_FUNC) &_simmer_get_queue_count_selected_, 2}, + {"_simmer_get_seized_", (DL_FUNC) &_simmer_get_seized_, 2}, + {"_simmer_get_seized_selected_", (DL_FUNC) &_simmer_get_seized_selected_, 2}, {"_simmer_get_selected_", (DL_FUNC) &_simmer_get_selected_, 2}, {"_simmer_Simulator__new", (DL_FUNC) &_simmer_Simulator__new, 4}, {"_simmer_reset_", (DL_FUNC) &_simmer_reset_, 1}, diff --git a/src/activity.cpp b/src/activity.cpp index 3c06318f..f4bbebc1 100644 --- a/src/activity.cpp +++ b/src/activity.cpp @@ -60,6 +60,16 @@ SEXP Release__new_func(const std::string& resource, const Function& amount) { return XPtr >(new Release(resource, amount)); } +//[[Rcpp::export]] +SEXP ReleaseAll__new(const std::string& resource) { + return XPtr >(new Release(resource)); +} + +//[[Rcpp::export]] +SEXP ReleaseAll__new_void() { + return XPtr >(new Release()); +} + //[[Rcpp::export]] SEXP ReleaseSelected__new(int id, int amount) { return XPtr >(new Release(id, amount)); @@ -70,6 +80,11 @@ SEXP ReleaseSelected__new_func(int id, const Function& amount) { return XPtr >(new Release(id, amount)); } +//[[Rcpp::export]] +SEXP ReleaseSelectedAll__new(int id) { + return XPtr >(new Release(id)); +} + //[[Rcpp::export]] SEXP SetCapacity__new(const std::string& resource, double value, char mod) { return XPtr >(new SetCapacity(resource, value, mod)); @@ -392,20 +407,17 @@ SEXP Log__new_func(const Function& message, int level) { //[[Rcpp::export]] int activity_get_count_(SEXP activity_) { - XPtr activity(activity_); - return activity->count; + return XPtr(activity_)->count; } //[[Rcpp::export]] void activity_print_(SEXP activity_, int indent, bool verbose) { - XPtr activity(activity_); - return activity->print(indent, verbose); + return XPtr(activity_)->print(indent, verbose); } //[[Rcpp::export]] SEXP activity_get_next_(SEXP activity_) { - XPtr activity(activity_); - Activity* the_next = activity->get_next(); + Activity* the_next = XPtr(activity_)->get_next(); if (the_next) return XPtr(the_next, false); return R_NilValue; @@ -413,8 +425,7 @@ SEXP activity_get_next_(SEXP activity_) { //[[Rcpp::export]] SEXP activity_get_prev_(SEXP activity_) { - XPtr activity(activity_); - Activity* the_prev = activity->get_prev(); + Activity* the_prev = XPtr(activity_)->get_prev(); if (the_prev) return XPtr(the_prev, false); return R_NilValue; @@ -430,6 +441,5 @@ void activity_chain_(SEXP first_, SEXP second_) { //[[Rcpp::export]] SEXP activity_clone_(SEXP activity_) { - XPtr activity(activity_); - return XPtr(activity->clone()); + return XPtr(XPtr(activity_)->clone()); } diff --git a/src/monitor.cpp b/src/monitor.cpp index 023f6086..319988ff 100644 --- a/src/monitor.cpp +++ b/src/monitor.cpp @@ -36,18 +36,15 @@ SEXP CsvMonitor__new(const std::string& ends_path, const std::string& releases_p //[[Rcpp::export]] DataFrame get_arrivals_(SEXP mon_, bool per_resource) { - XPtr mon(mon_); - return mon->get_arrivals(per_resource); + return XPtr(mon_)->get_arrivals(per_resource); } //[[Rcpp::export]] DataFrame get_attributes_(SEXP mon_) { - XPtr mon(mon_); - return mon->get_attributes(); + return XPtr(mon_)->get_attributes(); } //[[Rcpp::export]] DataFrame get_resources_(SEXP mon_) { - XPtr mon(mon_); - return mon->get_resources(); + return XPtr(mon_)->get_resources(); } diff --git a/src/process.cpp b/src/process.cpp index 65438172..93d1bc2b 100644 --- a/src/process.cpp +++ b/src/process.cpp @@ -43,8 +43,7 @@ std::vector get_trajectory_(SEXP sim_, const std::vector sim(sim_); - return sim->get_running_arrival()->name; + return XPtr(sim_)->get_running_arrival()->name; } //[[Rcpp::export]] @@ -65,8 +64,7 @@ NumericVector get_attribute_(SEXP sim_, const std::vector& keys, bo //[[Rcpp::export]] IntegerVector get_prioritization_(SEXP sim_) { - XPtr sim(sim_); - Arrival* a = sim->get_running_arrival(); + Arrival* a = XPtr(sim_)->get_running_arrival(); return IntegerVector::create( a->order.get_priority(), a->order.get_preemptible(), (int)a->order.get_restart() ); diff --git a/src/resource.cpp b/src/resource.cpp index cb7f92ba..06eff6a1 100644 --- a/src/resource.cpp +++ b/src/resource.cpp @@ -35,14 +35,8 @@ template VEC get_param(SEXP sim_, int id, const Fn& param) { XPtr sim(sim_); VEC out; - if (id >= 0) { - if (Resource* r = sim->get_running_arrival()->get_resource_selected(id)) - out.push_back(param(r)); - } else { - int i = 0; - while (Resource* r = sim->get_running_arrival()->get_resource_selected(i++)) - out.push_back(param(r)); - } + if (Resource* r = sim->get_running_arrival()->get_resource_selected(id)) + out.push_back(param(r)); return out; } @@ -86,6 +80,18 @@ std::vector get_queue_count_selected_(SEXP sim_, int id) { return get_param(sim_, id, boost::mem_fn(&Resource::get_queue_count)); } +//[[Rcpp::export]] +std::vector get_seized_(SEXP sim_, const std::vector& names) { + Arrival* arrival = XPtr(sim_)->get_running_arrival(); + return get_param(sim_, names, BIND(&Resource::get_seized, _1, arrival)); +} + +//[[Rcpp::export]] +std::vector get_seized_selected_(SEXP sim_, int id) { + Arrival* arrival = XPtr(sim_)->get_running_arrival(); + return get_param(sim_, id, BIND(&Resource::get_seized, _1, arrival)); +} + std::string get_name(Resource* res) { return res->name; } //[[Rcpp::export]] diff --git a/src/simulator.cpp b/src/simulator.cpp index e1ca24f8..9970c4be 100644 --- a/src/simulator.cpp +++ b/src/simulator.cpp @@ -29,32 +29,27 @@ SEXP Simulator__new(const std::string& name, bool verbose, SEXP mon, int log_lev //[[Rcpp::export]] void reset_(SEXP sim_) { - XPtr sim(sim_); - sim->reset(); + XPtr(sim_)->reset(); } //[[Rcpp::export]] double now_(SEXP sim_) { - XPtr sim(sim_); - return sim->now(); + return XPtr(sim_)->now(); } //[[Rcpp::export]] DataFrame peek_(SEXP sim_, int steps) { - XPtr sim(sim_); - return sim->peek(steps); + return XPtr(sim_)->peek(steps); } //[[Rcpp::export]] void stepn_(SEXP sim_, unsigned int n) { - XPtr sim(sim_); - sim->step(n); + XPtr(sim_)->step(n); } //[[Rcpp::export]] void run_(SEXP sim_, double until) { - XPtr sim(sim_); - sim->run(until); + XPtr(sim_)->run(until); } //[[Rcpp::export]] @@ -165,6 +160,5 @@ bool add_global_manager_(SEXP sim_, const std::string& key, double init, //[[Rcpp::export]] void record_ongoing_(SEXP sim_, bool per_resource) { - XPtr sim(sim_); - sim->record_ongoing(per_resource); + XPtr(sim_)->record_ongoing(per_resource); } diff --git a/tests/testthat/test-trajectory-seize-release.R b/tests/testthat/test-trajectory-seize-release.R index fa763527..da1271e6 100644 --- a/tests/testthat/test-trajectory-seize-release.R +++ b/tests/testthat/test-trajectory-seize-release.R @@ -268,3 +268,36 @@ test_that("arrivals don't jump the queue if there is room in the server (2)", { expect_equal(arrs_ordered$end_time, c(20, 11, 21)) expect_equal(arrs_ordered$activity_time, c(10, 10, 10)) }) + +test_that("unknown amounts can be released", { + random <- function() sample(10, 1) + t <- trajectory() %>% + seize("res1", random) %>% + set_attribute("res1", function() get_seized(env, "res1")) %>% + seize("res2", random) %>% + set_attribute("res2", function() get_seized(env, "res2")) %>% + select("res3", id=0) %>% + seize_selected(random, id=0) %>% + set_attribute("res3", function() get_seized_selected(env, id=0)) %>% + select("res4", id=1) %>% + seize_selected(random, id=1) %>% + set_attribute("res4", function() get_seized_selected(env, id=1)) %>% + timeout(1) %>% + release_all("res1") %>% + release_selected_all(id=0) %>% + release_all() + + env <- simmer(verbose = TRUE) %>% + add_resource("res1", 10) %>% + add_resource("res2", 10) %>% + add_resource("res3", 10) %>% + add_resource("res4", 10) %>% + add_generator("dummy", t, at(0), mon=2) + + run(env, 1) + expect_true(all(get_server_count(env, paste0("res", 1:4)) > rep(0, 4))) + expect_equal(get_server_count(env, paste0("res", 1:4)), + get_mon_attributes(env)$value) + run(env) + expect_equal(get_server_count(env, paste0("res", 1:4)), rep(0, 4)) +}) diff --git a/tests/testthat/test-trajectory-select.R b/tests/testthat/test-trajectory-select.R index b84a3322..51230665 100644 --- a/tests/testthat/test-trajectory-select.R +++ b/tests/testthat/test-trajectory-select.R @@ -270,7 +270,7 @@ test_that("selections can be retrieved", { expect_error(run(env)) - expect_equal(get_selected(env, id=-1), c("res0", "res1")) + expect_equal(get_selected(env, id=-1), "res1") expect_equal(get_selected(env, id=0), "res0") expect_equal(get_selected(env, id=1), "res1") expect_equal(get_selected(env, id=2), character(0)) diff --git a/tests/testthat/test-trajectory.R b/tests/testthat/test-trajectory.R index e2b5fda9..77d535f4 100644 --- a/tests/testthat/test-trajectory.R +++ b/tests/testthat/test-trajectory.R @@ -50,6 +50,8 @@ t0 <- trajectory(verbose = TRUE) %>% untrap(function() "asdf") %>% wait() %>% log_(function() "asdf") %>% + release_all() %>% + release_selected_all() %>% release_selected(1) %>% release("nurse", 1) @@ -93,6 +95,8 @@ trajs <- c( trajectory(verbose = TRUE) %>% untrap(function() "asdf"), trajectory(verbose = TRUE) %>% wait(), trajectory(verbose = TRUE) %>% log_(function() "asdf"), + trajectory(verbose = TRUE) %>% release_all(), + trajectory(verbose = TRUE) %>% release_selected_all(), trajectory(verbose = TRUE) %>% release_selected(1), trajectory(verbose = TRUE) %>% release("nurse", 1) )