1 /* 2 Copyright (c) 2005-2021 Intel Corporation 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 // Header guard and namespace names follow rml conventions. 18 19 #ifndef __RML_rml_base_H 20 #define __RML_rml_base_H 21 22 #include <cstddef> 23 24 #if _WIN32||_WIN64 25 #include <windows.h> 26 #endif /* _WIN32||_WIN64 */ 27 28 #ifdef RML_PURE_VIRTUAL_HANDLER 29 #define RML_PURE(T) {RML_PURE_VIRTUAL_HANDLER(); return (T)0;} 30 #else 31 #define RML_PURE(T) = 0; 32 #endif 33 34 namespace rml { 35 36 class server; 37 38 class versioned_object { 39 public: 40 //! A version number 41 typedef unsigned version_type; 42 ~versioned_object()43 virtual ~versioned_object() {} 44 45 //! Get version of this object 46 /** The version number is incremented when a incompatible change is introduced. 47 The version number is invariant for the lifetime of the object. */ 48 virtual version_type version() const RML_PURE(version_type) 49 50 }; 51 52 //! Represents a client's job for an execution context. 53 /** A job object is constructed by the client. 54 Not derived from versioned_object because version is same as for client. */ 55 class job { 56 friend class server; 57 }; 58 59 //! Information that client provides to server when asking for a server. 60 /** The instance must endure at least until acknowledge_close_connection is called. */ 61 class client: public versioned_object { 62 public: 63 //! Typedef for convenience of derived classes in other namespaces. 64 typedef ::rml::job job; 65 66 //! Index of a job in a job pool 67 typedef unsigned size_type; 68 69 //! Maximum number of threads that client can exploit profitably if nothing else is running on the machine. 70 /** The returned value should remain invariant for the lifetime of the connection. [idempotent] */ 71 virtual size_type max_job_count() const RML_PURE(size_type) 72 73 //! Minimum stack size for each job. 0 means to use default stack size. [idempotent] 74 virtual std::size_t min_stack_size() const RML_PURE(std::size_t) 75 76 //! Server calls this routine when it needs client to create a job object. 77 virtual job* create_one_job() RML_PURE(job*) 78 79 //! Acknowledge that all jobs have been cleaned up. 80 /** Called by server in response to request_close_connection 81 after cleanup(job) has been called for each job. */ 82 virtual void acknowledge_close_connection() RML_PURE(void) 83 84 //! Inform client that server is done with *this. 85 /** Client should destroy the job. 86 Not necessarily called by execution context represented by *this. 87 Never called while any other thread is working on the job. */ 88 virtual void cleanup( job& ) RML_PURE(void) 89 90 // In general, we should not add new virtual methods, because that would 91 // break derived classes. Think about reserving some vtable slots. 92 }; 93 94 // Information that server provides to client. 95 // Virtual functions are routines provided by the server for the client to call. 96 class server: public versioned_object { 97 public: 98 //! Typedef for convenience of derived classes. 99 typedef ::rml::job job; 100 101 #if _WIN32||_WIN64 102 typedef void* execution_resource_t; 103 #endif 104 105 //! Request that connection to server be closed. 106 /** Causes each job associated with the client to have its cleanup method called, 107 possibly by a thread different than the thread that created the job. 108 This method can return before all cleanup methods return. 109 Actions that have to wait after all cleanup methods return should be part of 110 client::acknowledge_close_connection. 111 Pass true as exiting if request_close_connection() is called because exit() is 112 called. In that case, it is the client's responsibility to make sure all threads 113 are terminated. In all other cases, pass false. */ 114 virtual void request_close_connection( bool exiting = false ) = 0; 115 116 //! Called by client thread when it reaches a point where it cannot make progress until other threads do. 117 virtual void yield() = 0; 118 119 //! Called by client to indicate a change in the number of non-RML threads that are running. 120 /** This is a performance hint to the RML to adjust how many threads it should let run 121 concurrently. The delta is the change in the number of non-RML threads that are running. 122 For example, a value of 1 means the client has started running another thread, and a value 123 of -1 indicates that the client has blocked or terminated one of its threads. */ 124 virtual void independent_thread_number_changed( int delta ) = 0; 125 126 //! Default level of concurrency for which RML strives when there are no non-RML threads running. 127 /** Normally, the value is the hardware concurrency minus one. 128 The "minus one" accounts for the thread created by main(). */ 129 virtual unsigned default_concurrency() const = 0; 130 }; 131 132 class factory { 133 public: 134 //! status results 135 enum status_type { 136 st_success=0, 137 st_connection_exists, 138 st_not_found, 139 st_incompatible 140 }; 141 142 protected: 143 //! Pointer to routine that waits for server to indicate when client can close itself. 144 status_type (*my_wait_to_close_routine)( factory& ); 145 146 public: 147 //! Library handle for use by RML. 148 #if _WIN32||_WIN64 149 HMODULE library_handle; 150 #else 151 void* library_handle; 152 #endif /* _WIN32||_WIN64 */ 153 154 //! Special marker to keep dll from being unloaded prematurely 155 static const std::size_t c_dont_unload = 1; 156 }; 157 158 //! Typedef for callback functions to print server info 159 typedef void (*server_info_callback_t)( void* arg, const char* server_info ); 160 161 } // namespace rml 162 163 #endif /* __RML_rml_base_H */ 164