Update BasicApi.md file

Signed-off-by: Vitalii Koshura <lestat.de.lionkur@gmail.com>
Vitalii Koshura 2023-02-21 01:13:12 +01:00
parent e02e5d6ba4
commit 676fe95ef3
No known key found for this signature in database
GPG Key ID: CE0DB1726070A5A3
1 changed files with 122 additions and 134 deletions

@ -1,120 +1,116 @@
[[PageOutline]]
# The BOINC application programming interface (API)
The BOINC API is a set of C++ functions.
Most of the functions have a C interface,
so that they can be used from programs written in C and other languages.
Unless otherwise specified, the functions return an integer error code;
zero indicates success.
To use the API include the header file:
#include "boinc_api.h"
```
#include "boinc_api.h"
```
BOINC applications may have an associate graphics program,
which can act as a screensaver.
The API for these graphics apps is [here](GraphicsApps).
# Initialization #init
# Initialization
Initialization must be done before calling other BOINC functions.
For sequential (single-threaded) apps, call
boinc_init();
```
boinc_init();
```
## Parallel apps
# Parallel apps
If your uses multiple threads or processes for parallelism, initialize using
BOINC_OPTIONS options;
boinc_options_defaults(options);
options.multi_thread = true; // if your app's main process uses multiple threads
options.multi_process = true; // if your app uses multiple processes
boinc_init_options(&options);
```
BOINC_OPTIONS options;
boinc_options_defaults(options);
options.multi_thread = true; // if your app's main process uses multiple threads
options.multi_process = true; // if your app uses multiple processes
boinc_init_options(&options);
```
Do this before creating any threads or processes, or storing the PID.
## GPU and coprocessor apps
# GPU and coprocessor apps
If your app uses GPUs or coprocessors, initialize using
BOINC_OPTIONS options;
boinc_options_defaults(options);
options.normal_thread_priority = true;
boinc_init_options(&options);
```
BOINC_OPTIONS options;
boinc_options_defaults(options);
options.normal_thread_priority = true;
boinc_init_options(&options);
```
On Windows, this causes the application to run at normal thread priority,
so that the GPU will run at full speed even if the CPUs are loaded.
# Termination
When the application has completed it must call
#!c++
int boinc_finish(int status);
```c++
int boinc_finish(int status);
```
`status` is nonzero if an error was encountered.
This call does not return.
Do *not* call `exit(0)`.
Do **not** call `exit(0)`.
If you do, BOINC will restart the app, which is probably not what you want.
Alternatively, if you want to show a message to the user
(e.g. because of an error condition that the user can remedy) use
boinc_finish_message(int status, const char* msg, bool is_notice);
If *is_notice* is true, the message will be shown as a notice in the GUI
```
boinc_finish_message(int status, const char* msg, bool is_notice);
```
If **is_notice** is true, the message will be shown as a notice in the GUI
(works with 7.5+ clients; for others, no message will be shown).
# Resolving file names #filenames
# Resolving file names
Applications that use named input or output files must call
#!c++
int boinc_resolve_filename(char *logical_name, char *physical_name, int len);
```c++
int boinc_resolve_filename(char *logical_name, char *physical_name, int len);
```
or
#!c++
int boinc_resolve_filename_s(char *logical_name, std::string& physical_name);
```c++
### int boinc_resolve_filename_s(char *logical_name, std
string& physical_name);
```
to convert logical file names to physical names. For example, instead of
#!c++
f = fopen("my_file", "r");
```c++
f = fopen("my_file", "r");
```
the application might use
#!c++
string resolved_name;
retval = boinc_resolve_filename_s("my_file", resolved_name);
if (retval) fail("can't resolve filename");
f = boinc_fopen(resolved_name.c_str(), "r");
```c++
string resolved_name;
retval = boinc_resolve_filename_s("my_file", resolved_name);
if (retval) fail("can't resolve filename");
f = boinc_fopen(resolved_name.c_str(), "r");
```
Don't use `boinc_resolve_filename()` for files with the *copy_file* attribute,
Don't use `boinc_resolve_filename()` for files with the **copy_file** attribute,
or for temporary files.
It must be used for all other input or output files specified in the job templates,
or files that are part of the application version.
# I/O wrappers #fopen
# I/O wrappers
Applications should replace `fopen()` calls with
#!c++
boinc_fopen(char* path, char* mode);
```c++
boinc_fopen(char* path, char* mode);
```
This deals with platform-specific problems.
On Windows, where security and indexing programs can briefly lock files,
@ -122,11 +118,11 @@ On Windows, where security and indexing programs can briefly lock files,
On Unix, where signals can cause `fopen()` to fail with `EINTR`,
`boinc_fopen` checks for this and does a few retries; it also sets the 'close-on-exec' flag.
# Checkpointing #checkpointing
# Checkpointing
Long jobs may want to periodically
write the current state of the computation to disk.
This is known as *checkpointing*.
This is known as **checkpointing**.
The checkpoint file must include everything required to restart the computation
at the same point.
On startup, the application reads the checkpoint file to determine where to begin computation.
@ -137,23 +133,21 @@ Most applications are able to checkpoint only at specific points,
e.g. at the end the outer loop.
Whan the application is at such a point, it must call
#!c++
int boinc_time_to_checkpoint();
```c++
int boinc_time_to_checkpoint();
```
If this returns nonzero (True) then the application should checkpoint immediately
(i.e., write the state file and flush all output files), then call
#!c++
void boinc_checkpoint_completed();
```c++
void boinc_checkpoint_completed();
```
`boinc_time_to_checkpoint()` is fast,
so it can be called frequently (hundreds or thousands of times a second).
*boinc_time_to_checkpoint* returns true only when sufficient time
**boinc_time_to_checkpoint** returns true only when sufficient time
has passed since the last checkpoint.
This minimum interval is the maximum of:
@ -161,9 +155,9 @@ This minimum interval is the maximum of:
(e.g. laptop users might want to checkpoint infrequently).
* An optional application-supplied, specified by calling
boinc_set_min_checkpoint_period(int nsecs);
```
boinc_set_min_checkpoint_period(int nsecs);
```
If you're using replication, make sure your application generates the same results
regardless of where and how often it restarts.
@ -173,64 +167,61 @@ This requires:
* If your app uses random numbers, save and restore the state of the RNG.
If you use rand(), you can do this by surrounding every boinc_time_to_checkpoint()
with the following:
int x = rand();
if (boinc_time_to_checkpoint()) {
...
}
srand(x);
```
int x = rand();
if (boinc_time_to_checkpoint()) {
...
}
srand(x);
```
Write x to the checkpoint file,
and do a srand(x) when restarting from a checkpoint.
# Critical sections #critical_sections
# Critical sections
#!c++
void boinc_begin_critical_section();
void boinc_end_critical_section();
```c++
void boinc_begin_critical_section();
void boinc_end_critical_section();
```
Call these around code segments during which you don't want to be
suspended or killed by the core client.
Since r14694, critical sections are reentrant.
This means that you can begin critical section multiple times,
but each `begin` must have a matching `end` call.
but each ```begin``` must have a matching ```end``` call.
*NOTE:* This is done automatically while checkpointing.
**NOTE:** This is done automatically while checkpointing.
# Atomic file update
To facilitate atomic checkpoint,
an application can write to output and state files using the `MFILE` class.
#!c++
class MFILE {
public:
int open(char* path, char* mode);
int _putchar(char);
int puts(char*);
int printf(char* format, ...);
size_t write(const void* buf, size_t size, size_t nitems);
int close();
int flush();
};
```c++
class MFILE {
public:
int open(char* path, char* mode);
int _putchar(char);
int puts(char*);
int printf(char* format, ...);
size_t write(const void* buf, size_t size, size_t nitems);
int close();
int flush();
};
```
MFILE buffers data in memory and writes to disk only on `flush()` or `close()`.
This lets you write output files and state files more or less atomically.
# Reporting progress #progress
# Reporting progress
The BOINC Manager displays the percent done of tasks in progress.
To keep this display current, an application should periodically call
#!c++
boinc_fraction_done(double fraction_done);
```c++
boinc_fraction_done(double fraction_done);
```
The `fraction_done` argument is an estimate of the workunit fraction complete (from 0 to 1).
This function is fast and can be called frequently (once per second or more).
@ -244,22 +235,22 @@ If your application can supply an accurate fraction done, set the
# Timing information
#!c++
int boinc_wu_cpu_time(double &cpu_time);
```c++
int boinc_wu_cpu_time(double &cpu_time);
```
gets the total CPU time (from the beginning of the work unit, not just since the last restart).
double boinc_elapsed_time();
```
double boinc_elapsed_time();
```
returns the elapsed runtime (i.e. wall-clock time during which the job
was not suspended) since the start of the current episode.
The elapsed time from earlier episodes is in APP_INIT_DATA::starting_elapsed_time
### The elapsed time from earlier episodes is in APP_INIT_DATA
starting_elapsed_time
(only from 6.10+ clients).
# Standalone mode #standalone
# Standalone mode
BOINC applications can be run in "standalone" mode for testing,
or under the control of the BOINC client.
@ -269,21 +260,19 @@ if the application is running standalone.
To determine if the application is running in standalone mode or
under the control of the BOINC client, call
#!c++
int boinc_is_standalone(void);
```c++
int boinc_is_standalone(void);
```
This returns non-zero (True) if the application is running standalone,
and zero (False) if the application is running under the control of the BOINC client.
# Registering a timer handler #timer
# Registering a timer handler
#!c++
typedef void (*FUNC_PTR)();
void boinc_register_timer_callback(FUNC_PTR);
```c++
typedef void (*FUNC_PTR)();
void boinc_register_timer_callback(FUNC_PTR);
```
This registers a timer handler function,
which will be called once per second.
@ -293,17 +282,16 @@ which will be called once per second.
If an application is unable to run because of a transient condition,
it should call
#!c++
int boinc_temporary_exit(int delay, const char* reason=NULL, bool is_notice=false);
```c++
int boinc_temporary_exit(int delay, const char* reason=NULL, bool is_notice=false);
```
This will exit the application and tell the BOINC client to restart it
again in at least *delay* seconds.
again in at least **delay** seconds.
(This works with 6.10.25+ client;
on other clients, it will potentially restart immediately).
*Reason*, if supplied, is shown to the user as the explanation for the deferral.
If *is_notice* is true, it's shown as a notice
**Reason**, if supplied, is shown to the user as the explanation for the deferral.
If **is_notice** is true, it's shown as a notice
(this should be used only for conditions that the user can fix).
Examples: