1/*
2 Copyright (c) 2005-2019 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
34namespace rml {
35
36//! Base class for denying assignment and copy constructor.
37class no_copy {
38 void operator=( no_copy& );
39 no_copy( no_copy& );
40public:
41 no_copy() {}
42};
43
44class server;
45
46class versioned_object {
47public:
48 //! A version number
49 typedef unsigned version_type;
50
51 //! Get version of this object
52 /** The version number is incremented when a incompatible change is introduced.
53 The version number is invariant for the lifetime of the object. */
54 virtual version_type version() const RML_PURE(version_type)
55};
56
57//! Represents a client's job for an execution context.
58/** A job object is constructed by the client.
59 Not derived from versioned_object because version is same as for client. */
60class job {
61 friend class server;
62
63 //! Word for use by server
64 /** Typically the server uses it to speed up internal lookup.
65 Clients must not modify the word. */
66 void* scratch_ptr;
67};
68
69//! Information that client provides to server when asking for a server.
70/** The instance must endure at least until acknowledge_close_connection is called. */
71class client: public versioned_object {
72public:
73 //! Typedef for convenience of derived classes in other namespaces.
74 typedef ::rml::job job;
75
76 //! Index of a job in a job pool
77 typedef unsigned size_type;
78
79 //! Maximum number of threads that client can exploit profitably if nothing else is running on the machine.
80 /** The returned value should remain invariant for the lifetime of the connection. [idempotent] */
81 virtual size_type max_job_count() const RML_PURE(size_type)
82
83 //! Minimum stack size for each job. 0 means to use default stack size. [idempotent]
84 virtual std::size_t min_stack_size() const RML_PURE(std::size_t)
85
86 //! Server calls this routine when it needs client to create a job object.
87 virtual job* create_one_job() RML_PURE(job*)
88
89 //! Acknowledge that all jobs have been cleaned up.
90 /** Called by server in response to request_close_connection
91 after cleanup(job) has been called for each job. */
92 virtual void acknowledge_close_connection() RML_PURE(void)
93
94 enum policy_type {turnaround,throughput};
95
96 //! Inform server of desired policy. [idempotent]
97 virtual policy_type policy() const RML_PURE(policy_type)
98
99 //! Inform client that server is done with *this.
100 /** Client should destroy the job.
101 Not necessarily called by execution context represented by *this.
102 Never called while any other thread is working on the job. */
103 virtual void cleanup( job& ) RML_PURE(void)
104
105 // In general, we should not add new virtual methods, because that would
106 // break derived classes. Think about reserving some vtable slots.
107};
108
109// Information that server provides to client.
110// Virtual functions are routines provided by the server for the client to call.
111class server: public versioned_object {
112public:
113 //! Typedef for convenience of derived classes.
114 typedef ::rml::job job;
115
116#if _WIN32||_WIN64
117 typedef void* execution_resource_t;
118#endif
119
120 //! Request that connection to server be closed.
121 /** Causes each job associated with the client to have its cleanup method called,
122 possibly by a thread different than the thread that created the job.
123 This method can return before all cleanup methods return.
124 Actions that have to wait after all cleanup methods return should be part of
125 client::acknowledge_close_connection.
126 Pass true as exiting if request_close_connection() is called because exit() is
127 called. In that case, it is the client's responsibility to make sure all threads
128 are terminated. In all other cases, pass false. */
129 virtual void request_close_connection( bool exiting = false ) = 0;
130
131 //! Called by client thread when it reaches a point where it cannot make progress until other threads do.
132 virtual void yield() = 0;
133
134 //! Called by client to indicate a change in the number of non-RML threads that are running.
135 /** This is a performance hint to the RML to adjust how many threads it should let run
136 concurrently. The delta is the change in the number of non-RML threads that are running.
137 For example, a value of 1 means the client has started running another thread, and a value
138 of -1 indicates that the client has blocked or terminated one of its threads. */
139 virtual void independent_thread_number_changed( int delta ) = 0;
140
141 //! Default level of concurrency for which RML strives when there are no non-RML threads running.
142 /** Normally, the value is the hardware concurrency minus one.
143 The "minus one" accounts for the thread created by main(). */
144 virtual unsigned default_concurrency() const = 0;
145
146protected:
147 static void*& scratch_ptr( job& j ) {return j.scratch_ptr;}
148};
149
150class factory {
151public:
152 //! status results
153 enum status_type {
154 st_success=0,
155 st_connection_exists,
156 st_not_found,
157 st_incompatible
158 };
159
160 //! Scratch pointer for use by RML.
161 void* scratch_ptr;
162
163protected:
164 //! Pointer to routine that waits for server to indicate when client can close itself.
165 status_type (*my_wait_to_close_routine)( factory& );
166
167public:
168 //! Library handle for use by RML.
169#if _WIN32||_WIN64
170 HMODULE library_handle;
171#else
172 void* library_handle;
173#endif /* _WIN32||_WIN64 */
174
175 //! Special marker to keep dll from being unloaded prematurely
176 static const std::size_t c_dont_unload = 1;
177};
178
179//! Typedef for callback functions to print server info
180typedef void (*server_info_callback_t)( void* arg, const char* server_info );
181
182} // namespace rml
183
184#endif /* __RML_rml_base_H */
185