Skip to content

Commit

Permalink
Refactor repository_toolkit to remove boilerplate specializations for…
Browse files Browse the repository at this point in the history
… non-standard integration types

- repository_toolkit() used a set of complete function specializations to extract content group records from a repository, or to remove a record. Since function specializations must be complete, this required specializations for each combination of ‘number’ and ‘Payload’

- standard specializations were provided for number = float, double, long double. But for other types it was necessary to provide suitable specializations for each payload type. This is quite onerous

- a better solution is to embed this function in a class and partially specialize the class. The result works for any choice of ‘number’, with specializations needed only for each choice of payload
  • Loading branch information
ds283 committed Jul 23, 2017
1 parent 3849785 commit 23862fb
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 105 deletions.
179 changes: 77 additions & 102 deletions CppTransport/transport-runtime/repository/repository_toolkit.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,135 +44,103 @@ namespace transport

namespace repository_toolkit_impl
{

//! template method to extract a content group
//! template method to get content group record from repository
template <typename number, typename Payload>
std::unique_ptr< content_group_record<Payload> > get_rw_content_group(repository<number>& repo, const std::string& name, transaction_manager& mgr);


//! specialize for integration payloads
template <>
std::unique_ptr< content_group_record< integration_payload> > get_rw_content_group(repository<double>& repo, const std::string& name, transaction_manager& mgr)
struct get_rw_content_group
{
return repo.query_integration_content(name, mgr);
}

std::unique_ptr< content_group_record<Payload> >
get(repository<number>& repo, const std::string& name, transaction_manager& mgr);

};

template <>
std::unique_ptr< content_group_record< integration_payload> > get_rw_content_group(repository<float>& repo, const std::string& name, transaction_manager& mgr)
{
return repo.query_integration_content(name, mgr);
}

template <>
std::unique_ptr< content_group_record< integration_payload> > get_rw_content_group(repository<long double>& repo, const std::string& name, transaction_manager& mgr)
//! specialize for integration payloads
template <typename number>
struct get_rw_content_group<number, integration_payload>
{
return repo.query_integration_content(name, mgr);
}

std::unique_ptr< content_group_record< integration_payload > >
get(repository<number>& repo, const std::string& name, transaction_manager& mgr)
{
return repo.query_integration_content(name, mgr);
}

};

//! specialize for postintegration payloads
template <>
std::unique_ptr< content_group_record< postintegration_payload> > get_rw_content_group(repository<double>& repo, const std::string& name, transaction_manager& mgr)
{
return repo.query_postintegration_content(name, mgr);
}

template <>
std::unique_ptr< content_group_record< postintegration_payload> > get_rw_content_group(repository<float>& repo, const std::string& name, transaction_manager& mgr)
template <typename number>
struct get_rw_content_group<number, postintegration_payload>
{
return repo.query_postintegration_content(name, mgr);
}

template <>
std::unique_ptr< content_group_record< postintegration_payload> > get_rw_content_group(repository<long double>& repo, const std::string& name, transaction_manager& mgr)
{
return repo.query_postintegration_content(name, mgr);
}

std::unique_ptr< content_group_record< postintegration_payload > >
get(repository<number>& repo, const std::string& name, transaction_manager& mgr)
{
return repo.query_postintegration_content(name, mgr);
}

};

//! specialize for output payloads
template <>
std::unique_ptr< content_group_record< output_payload> > get_rw_content_group(repository<double>& repo, const std::string& name, transaction_manager& mgr)
{
return repo.query_output_content(name, mgr);
}

template <>
std::unique_ptr< content_group_record< output_payload> > get_rw_content_group(repository<float>& repo, const std::string& name, transaction_manager& mgr)
template <typename number>
struct get_rw_content_group<number, output_payload>
{
return repo.query_output_content(name, mgr);
}

template <>
std::unique_ptr< content_group_record< output_payload> > get_rw_content_group(repository<long double>& repo, const std::string& name, transaction_manager& mgr)
{
return repo.query_output_content(name, mgr);
}
std::unique_ptr< content_group_record< output_payload > >
get(repository<number>& repo, const std::string& name, transaction_manager& mgr)
{
return repo.query_output_content(name, mgr);
}

};


//! template method to delete a content group
template <typename number, typename Payload>
void erase_repository_record(repository<number>& repo, const std::string& name, const std::string& task_name, transaction_manager& mgr);


// specialize for integration payloads
template <>
void erase_repository_record<double, integration_payload>(repository<double>& repo, const std::string& name, const std::string& task_name, transaction_manager& mgr)
struct erase_repository_record
{
repo.delete_integration_content(name, task_name, mgr);
}

void erase(repository<number>& repo, const std::string& name, const std::string& task_name, transaction_manager& mgr);

};

template <>
void erase_repository_record<float, integration_payload>(repository<float>& repo, const std::string& name, const std::string& task_name, transaction_manager& mgr)
{
repo.delete_integration_content(name, task_name, mgr);
}

template <>
void erase_repository_record<long double, integration_payload>(repository<long double>& repo, const std::string& name, const std::string& task_name, transaction_manager& mgr)
// specialize for integration payloads
template <typename number>
struct erase_repository_record<number, integration_payload>
{
repo.delete_integration_content(name, task_name, mgr);
}

void erase(repository<number>& repo, const std::string& name, const std::string& task_name, transaction_manager& mgr)
{
repo.delete_integration_content(name, task_name, mgr);
}

};

// specialize for postintegration payloads
template <>
void erase_repository_record<double, postintegration_payload>(repository<double>& repo, const std::string& name, const std::string& task_name, transaction_manager& mgr)
template <typename number>
struct erase_repository_record<number, postintegration_payload>
{
repo.delete_postintegration_content(name, task_name, mgr);
}

template <>
void erase_repository_record<float, postintegration_payload>(repository<float>& repo, const std::string& name, const std::string& task_name, transaction_manager& mgr)
{
repo.delete_postintegration_content(name, task_name, mgr);
}

template <>
void erase_repository_record<long double, postintegration_payload>(repository<long double>& repo, const std::string& name, const std::string& task_name, transaction_manager& mgr)
{
repo.delete_postintegration_content(name, task_name, mgr);
}

void erase(repository<number>& repo, const std::string& name, const std::string& task_name, transaction_manager& mgr)
{
repo.delete_postintegration_content(name, task_name, mgr);
}

};

// specialize for output payloads
template <>
void erase_repository_record<double, output_payload>(repository<double>& repo, const std::string& name, const std::string& task_name, transaction_manager& mgr)
template <typename number>
struct erase_repository_record<number, output_payload>
{
repo.delete_output_content(name, task_name, mgr);
}

template <>
void erase_repository_record<float, output_payload>(repository<float>& repo, const std::string& name, const std::string& task_name, transaction_manager& mgr)
{
repo.delete_output_content(name, task_name, mgr);
}

template <>
void erase_repository_record<long double, output_payload>(repository<long double>& repo, const std::string& name, const std::string& task_name, transaction_manager& mgr)
{
repo.delete_output_content(name, task_name, mgr);
}
void erase(repository<number>& repo, const std::string& name, const std::string& task_name, transaction_manager& mgr)
{
repo.delete_output_content(name, task_name, mgr);
}

};

} // namespace repository_toolkit_impl

Expand Down Expand Up @@ -333,7 +301,9 @@ namespace transport
t.second = true;

// re-query the database to get a read/write version of this record
typename ContentDatabase::mapped_type rw_record = get_rw_content_group<number, typename ContentDatabase::mapped_type::element_type::payload_type>(this->repo, record.get_name(), mgr);
typename ContentDatabase::mapped_type rw_record =
get_rw_content_group<number, typename ContentDatabase::mapped_type::element_type::payload_type>{}.get(
this->repo, record.get_name(), mgr);

if(rw_record->get_lock_status())
{
Expand Down Expand Up @@ -443,7 +413,8 @@ namespace transport
msg << CPPTRANSPORT_REPO_TOOLKIT_DELETING_OBJECT << " '" << record.get_name() << "'";
this->msg(msg.str());

erase_repository_record<number, typename ContentDatabase::mapped_type::element_type::payload_type>(this->repo, record.get_name(), record.get_task_name(),mgr);
erase_repository_record<number, typename ContentDatabase::mapped_type::element_type::payload_type>{}.erase(
this->repo, record.get_name(), record.get_task_name(),mgr);

// erase record and reset iterator to point to following element
t = db.erase(t);
Expand Down Expand Up @@ -538,7 +509,9 @@ namespace transport
t.second = true;

// re-query the database to get a read/write version of this record
typename ContentDatabase::mapped_type rw_record = get_rw_content_group<number, typename ContentDatabase::mapped_type::element_type::payload_type>(this->repo, record.get_name(), mgr);
typename ContentDatabase::mapped_type rw_record =
get_rw_content_group<number, typename ContentDatabase::mapped_type::element_type::payload_type>{}.get(
this->repo, record.get_name(), mgr);

rw_record->set_lock_status(true);

Expand Down Expand Up @@ -607,7 +580,9 @@ namespace transport
t.second = true;

// re-query the database to get a read/write version of this record
typename ContentDatabase::mapped_type rw_record = get_rw_content_group<number, typename ContentDatabase::mapped_type::element_type::payload_type>(this->repo, record.get_name(), mgr);
typename ContentDatabase::mapped_type rw_record =
get_rw_content_group<number, typename ContentDatabase::mapped_type::element_type::payload_type>{}.get(
this->repo, record.get_name(), mgr);

rw_record->set_lock_status(false);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,15 @@ namespace transport
// specialize for the basic data types; if more complex types are used,
// separate specializations will need to be provided
template <>
std::string data_type_name<float>() { return("float"); }
std::string data_type_name<float>() { return std::string{"float"}; }

template <>
std::string data_type_name<double>() { return("double"); }
std::string data_type_name<double>() { return std::string{"double"}; }

template <>
std::string data_type_name<long double>() { return("long double"); }
std::string data_type_name<long double>() { return std::string{"long double"}; }



// forward-declare integration writer
template <typename number> class integration_writer;
Expand Down

0 comments on commit 23862fb

Please sign in to comment.