Line data Source code
1 : /*
2 : * SPDX-License-Identifier: MPL-2.0
3 : *
4 : * This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this
6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 : *
8 : * Copyright 2024 MonetDB Foundation;
9 : * Copyright August 2008 - 2023 MonetDB B.V.;
10 : * Copyright 1997 - July 2008 CWI.
11 : */
12 :
13 : /*
14 : * @f alarm
15 : * @a M.L. Kersten, P. Boncz
16 : *
17 : * @+ Timers and Timed Interrupts
18 : * This module handles various signaling/timer functionalities.
19 : * The Monet interface supports two timer commands: @emph{ alarm} and @emph{ sleep}.
20 : * Their argument is the number of seconds to wait before the timer goes off.
21 : * The @emph{ sleep} command blocks till the alarm goes off.
22 : * The @emph{ alarm} command continues directly, executes off a
23 : * string when it goes off.
24 : * The parameterless routines @emph{ time} and @emph{ ctime} provide access to
25 : * the cpu clock.They return an integer and string, respectively.
26 : */
27 : #include "monetdb_config.h"
28 : #include "mal.h"
29 : #include "mal_client.h"
30 : #include "mal_interpreter.h"
31 : #include <time.h>
32 : #include "mal_exception.h"
33 :
34 : static str
35 30 : ALARMusec(lng *ret)
36 : {
37 30 : *ret = GDKusec();
38 30 : return MAL_SUCCEED;
39 : }
40 :
41 : #define SLEEP_SINGLE(TPE) \
42 : do { \
43 : TPE *res = getArgReference_##TPE(stk, pci, 0); \
44 : const TPE *msecs = getArgReference_##TPE(stk,pci,1); \
45 : if (is_##TPE##_nil(*msecs)) \
46 : throw(MAL, "alarm.sleep", "NULL values not allowed for sleeping time"); \
47 : if (*msecs < 0) \
48 : throw(MAL, "alarm.sleep", "Cannot sleep for a negative time"); \
49 : MT_sleep_ms((unsigned int) *msecs); \
50 : *res = *msecs; \
51 : } while (0)
52 :
53 : static str
54 10 : ALARMsleep(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
55 : {
56 10 : (void) cntxt;
57 10 : switch (getArgType(mb, pci, 1)) {
58 0 : case TYPE_bte:
59 0 : SLEEP_SINGLE(bte);
60 0 : break;
61 0 : case TYPE_sht:
62 0 : SLEEP_SINGLE(sht);
63 0 : break;
64 10 : case TYPE_int:
65 10 : SLEEP_SINGLE(int);
66 10 : break;
67 0 : default:
68 0 : throw(MAL, "alarm.sleep",
69 : SQLSTATE(42000) "Sleep function not available for type %s",
70 : ATOMname(getArgType(mb, pci, 1)));
71 : }
72 : return MAL_SUCCEED;
73 : }
74 :
75 : static str
76 0 : ALARMctime(str *res)
77 : {
78 0 : time_t t = time(0);
79 0 : char *base;
80 0 : char buf[26];
81 :
82 : #ifdef HAVE_CTIME_R3
83 : base = ctime_r(&t, buf, sizeof(buf));
84 : #else
85 0 : base = ctime_r(&t, buf);
86 : #endif
87 0 : if (base == NULL)
88 : /* very unlikely to happen... */
89 0 : throw(MAL, "alarm.ctime", "failed to format time");
90 :
91 0 : base[24] = 0; /* squash final newline */
92 0 : *res = GDKstrdup(base);
93 0 : if (*res == NULL)
94 0 : throw(MAL, "alarm.ctime", SQLSTATE(HY013) MAL_MALLOC_FAIL);
95 : return MAL_SUCCEED;
96 : }
97 :
98 : static str
99 0 : ALARMepoch(int *res)
100 : { /* XXX should be lng */
101 0 : *res = (int) time(0);
102 0 : return MAL_SUCCEED;
103 : }
104 :
105 : static str
106 0 : ALARMtime(int *res)
107 : {
108 0 : *res = GDKms();
109 0 : return MAL_SUCCEED;
110 : }
111 :
112 : #include "mel.h"
113 : mel_func alarm_init_funcs[] = {
114 : pattern("alarm", "sleep", ALARMsleep, true, "Sleep a few milliseconds", args(1,2, arg("",void),argany("msecs",1))),
115 : pattern("alarm", "sleep", ALARMsleep, true, "Sleep a few milliseconds and return the slept value", args(1,2, argany("",1),argany("msecs",1))),
116 : command("alarm", "usec", ALARMusec, true, "Return time since Jan 1, 1970 in microseconds.", args(1,1, arg("",lng))),
117 : command("alarm", "time", ALARMtime, true, "Return time since program start in milliseconds.", args(1,1, arg("",int))),
118 : command("alarm", "epoch", ALARMepoch, true, "Return time since Jan 1, 1970 in seconds.", args(1,1, arg("",int))),
119 : command("alarm", "ctime", ALARMctime, true, "Return the current time as a C-time string.", args(1,1, arg("",str))),
120 : { .imp=NULL }
121 : };
122 : #include "mal_import.h"
123 : #ifdef _MSC_VER
124 : #undef read
125 : #pragma section(".CRT$XCU",read)
126 : #endif
127 320 : LIB_STARTUP_FUNC(init_alarm_mal)
128 320 : { mal_module("alarm", NULL, alarm_init_funcs); }
|