Home | History | Annotate | Download | only in grpc
      1 /*
      2  *
      3  * Copyright 2015 gRPC authors.
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  *
     17  */
     18 
     19 #include "timeval.h"
     20 
     21 #include <ext/spl/spl_exceptions.h>
     22 #include <zend_exceptions.h>
     23 
     24 zend_class_entry *grpc_ce_timeval;
     25 PHP_GRPC_DECLARE_OBJECT_HANDLER(timeval_ce_handlers)
     26 
     27 /* Frees and destroys an instance of wrapped_grpc_call */
     28 PHP_GRPC_FREE_WRAPPED_FUNC_START(wrapped_grpc_timeval)
     29 PHP_GRPC_FREE_WRAPPED_FUNC_END()
     30 
     31 /* Initializes an instance of wrapped_grpc_timeval to be associated with an
     32  * object of a class specified by class_type */
     33 php_grpc_zend_object create_wrapped_grpc_timeval(zend_class_entry *class_type
     34                                                  TSRMLS_DC) {
     35   PHP_GRPC_ALLOC_CLASS_OBJECT(wrapped_grpc_timeval);
     36   zend_object_std_init(&intern->std, class_type TSRMLS_CC);
     37   object_properties_init(&intern->std, class_type);
     38   PHP_GRPC_FREE_CLASS_OBJECT(wrapped_grpc_timeval, timeval_ce_handlers);
     39 }
     40 
     41 zval *grpc_php_wrap_timeval(gpr_timespec wrapped TSRMLS_DC) {
     42   zval *timeval_object;
     43   PHP_GRPC_MAKE_STD_ZVAL(timeval_object);
     44   object_init_ex(timeval_object, grpc_ce_timeval);
     45   wrapped_grpc_timeval *timeval =
     46     PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_timeval, timeval_object);
     47   memcpy(&timeval->wrapped, &wrapped, sizeof(gpr_timespec));
     48   return timeval_object;
     49 }
     50 
     51 /**
     52  * Constructs a new instance of the Timeval class
     53  * @param long $microseconds The number of microseconds in the interval
     54  */
     55 PHP_METHOD(Timeval, __construct) {
     56   wrapped_grpc_timeval *timeval =
     57     PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_timeval, getThis());
     58   php_grpc_long microseconds;
     59 
     60   /* "l" == 1 long */
     61   if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &microseconds) ==
     62       FAILURE) {
     63     zend_throw_exception(spl_ce_InvalidArgumentException,
     64                          "Timeval expects a long", 1 TSRMLS_CC);
     65     return;
     66   }
     67   gpr_timespec time = gpr_time_from_micros(microseconds, GPR_TIMESPAN);
     68   memcpy(&timeval->wrapped, &time, sizeof(gpr_timespec));
     69 }
     70 
     71 /**
     72  * Adds another Timeval to this one and returns the sum. Calculations saturate
     73  * at infinities.
     74  * @param Timeval $other_obj The other Timeval object to add
     75  * @return Timeval A new Timeval object containing the sum
     76  */
     77 PHP_METHOD(Timeval, add) {
     78   zval *other_obj;
     79 
     80   /* "O" == 1 Object */
     81   if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &other_obj,
     82                             grpc_ce_timeval) == FAILURE) {
     83     zend_throw_exception(spl_ce_InvalidArgumentException,
     84                          "add expects a Timeval", 1 TSRMLS_CC);
     85     return;
     86   }
     87   wrapped_grpc_timeval *self =
     88     PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_timeval, getThis());
     89   wrapped_grpc_timeval *other =
     90     PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_timeval, other_obj);
     91   zval *sum =
     92     grpc_php_wrap_timeval(gpr_time_add(self->wrapped, other->wrapped)
     93                           TSRMLS_CC);
     94   RETURN_DESTROY_ZVAL(sum);
     95 }
     96 
     97 /**
     98  * Subtracts another Timeval from this one and returns the difference.
     99  * Calculations saturate at infinities.
    100  * @param Timeval $other_obj The other Timeval object to subtract
    101  * @return Timeval A new Timeval object containing the diff
    102  */
    103 PHP_METHOD(Timeval, subtract) {
    104   zval *other_obj;
    105 
    106   /* "O" == 1 Object */
    107   if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &other_obj,
    108                             grpc_ce_timeval) == FAILURE) {
    109     zend_throw_exception(spl_ce_InvalidArgumentException,
    110                          "subtract expects a Timeval", 1 TSRMLS_CC);
    111     return;
    112   }
    113   wrapped_grpc_timeval *self =
    114     PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_timeval, getThis());
    115   wrapped_grpc_timeval *other =
    116     PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_timeval, other_obj);
    117   zval *diff =
    118     grpc_php_wrap_timeval(gpr_time_sub(self->wrapped, other->wrapped)
    119                           TSRMLS_CC);
    120   RETURN_DESTROY_ZVAL(diff);
    121 }
    122 
    123 /**
    124  * Return negative, 0, or positive according to whether a < b, a == b,
    125  * or a > b respectively.
    126  * @param Timeval $a_obj The first time to compare
    127  * @param Timeval $b_obj The second time to compare
    128  * @return long
    129  */
    130 PHP_METHOD(Timeval, compare) {
    131   zval *a_obj;
    132   zval *b_obj;
    133 
    134   /* "OO" == 2 Objects */
    135   if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OO", &a_obj,
    136                             grpc_ce_timeval, &b_obj,
    137                             grpc_ce_timeval) == FAILURE) {
    138     zend_throw_exception(spl_ce_InvalidArgumentException,
    139                          "compare expects two Timevals", 1 TSRMLS_CC);
    140     return;
    141   }
    142   wrapped_grpc_timeval *a =
    143     PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_timeval, a_obj);
    144   wrapped_grpc_timeval *b =
    145     PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_timeval, b_obj);
    146   long result = gpr_time_cmp(a->wrapped, b->wrapped);
    147   RETURN_LONG(result);
    148 }
    149 
    150 /**
    151  * Checks whether the two times are within $threshold of each other
    152  * @param Timeval $a_obj The first time to compare
    153  * @param Timeval $b_obj The second time to compare
    154  * @param Timeval $thresh_obj The threshold to check against
    155  * @return bool True if $a and $b are within $threshold, False otherwise
    156  */
    157 PHP_METHOD(Timeval, similar) {
    158   zval *a_obj;
    159   zval *b_obj;
    160   zval *thresh_obj;
    161 
    162   /* "OOO" == 3 Objects */
    163   if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OOO", &a_obj,
    164                             grpc_ce_timeval, &b_obj, grpc_ce_timeval,
    165                             &thresh_obj, grpc_ce_timeval) == FAILURE) {
    166     zend_throw_exception(spl_ce_InvalidArgumentException,
    167                          "compare expects three Timevals", 1 TSRMLS_CC);
    168     return;
    169   }
    170   wrapped_grpc_timeval *a =
    171     PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_timeval, a_obj);
    172   wrapped_grpc_timeval *b =
    173     PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_timeval, b_obj);
    174   wrapped_grpc_timeval *thresh =
    175     PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_timeval, thresh_obj);
    176   int result = gpr_time_similar(a->wrapped, b->wrapped, thresh->wrapped);
    177   RETURN_BOOL(result);
    178 }
    179 
    180 /**
    181  * Returns the current time as a timeval object
    182  * @return Timeval The current time
    183  */
    184 PHP_METHOD(Timeval, now) {
    185   zval *now = grpc_php_wrap_timeval(gpr_now(GPR_CLOCK_REALTIME) TSRMLS_CC);
    186   RETURN_DESTROY_ZVAL(now);
    187 }
    188 
    189 /**
    190  * Returns the zero time interval as a timeval object
    191  * @return Timeval Zero length time interval
    192  */
    193 PHP_METHOD(Timeval, zero) {
    194   zval *grpc_php_timeval_zero =
    195     grpc_php_wrap_timeval(gpr_time_0(GPR_CLOCK_REALTIME) TSRMLS_CC);
    196   RETURN_DESTROY_ZVAL(grpc_php_timeval_zero);
    197 }
    198 
    199 /**
    200  * Returns the infinite future time value as a timeval object
    201  * @return Timeval Infinite future time value
    202  */
    203 PHP_METHOD(Timeval, infFuture) {
    204   zval *grpc_php_timeval_inf_future =
    205     grpc_php_wrap_timeval(gpr_inf_future(GPR_CLOCK_REALTIME) TSRMLS_CC);
    206   RETURN_DESTROY_ZVAL(grpc_php_timeval_inf_future);
    207 }
    208 
    209 /**
    210  * Returns the infinite past time value as a timeval object
    211  * @return Timeval Infinite past time value
    212  */
    213 PHP_METHOD(Timeval, infPast) {
    214   zval *grpc_php_timeval_inf_past =
    215     grpc_php_wrap_timeval(gpr_inf_past(GPR_CLOCK_REALTIME) TSRMLS_CC);
    216   RETURN_DESTROY_ZVAL(grpc_php_timeval_inf_past);
    217 }
    218 
    219 /**
    220  * Sleep until this time, interpreted as an absolute timeout
    221  * @return void
    222  */
    223 PHP_METHOD(Timeval, sleepUntil) {
    224   wrapped_grpc_timeval *this =
    225     PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_timeval, getThis());
    226   gpr_sleep_until(this->wrapped);
    227 }
    228 
    229 ZEND_BEGIN_ARG_INFO_EX(arginfo_construct, 0, 0, 1)
    230   ZEND_ARG_INFO(0, microseconds)
    231 ZEND_END_ARG_INFO()
    232 
    233 ZEND_BEGIN_ARG_INFO_EX(arginfo_add, 0, 0, 1)
    234   ZEND_ARG_INFO(0, timeval)
    235 ZEND_END_ARG_INFO()
    236 
    237 ZEND_BEGIN_ARG_INFO_EX(arginfo_compare, 0, 0, 2)
    238   ZEND_ARG_INFO(0, a_timeval)
    239   ZEND_ARG_INFO(0, b_timeval)
    240 ZEND_END_ARG_INFO()
    241 
    242 ZEND_BEGIN_ARG_INFO_EX(arginfo_infFuture, 0, 0, 0)
    243 ZEND_END_ARG_INFO()
    244 
    245 ZEND_BEGIN_ARG_INFO_EX(arginfo_infPast, 0, 0, 0)
    246 ZEND_END_ARG_INFO()
    247 
    248 ZEND_BEGIN_ARG_INFO_EX(arginfo_now, 0, 0, 0)
    249 ZEND_END_ARG_INFO()
    250 
    251 ZEND_BEGIN_ARG_INFO_EX(arginfo_similar, 0, 0, 3)
    252   ZEND_ARG_INFO(0, a_timeval)
    253   ZEND_ARG_INFO(0, b_timeval)
    254   ZEND_ARG_INFO(0, threshold_timeval)
    255 ZEND_END_ARG_INFO()
    256 
    257 ZEND_BEGIN_ARG_INFO_EX(arginfo_sleepUntil, 0, 0, 0)
    258 ZEND_END_ARG_INFO()
    259 
    260 ZEND_BEGIN_ARG_INFO_EX(arginfo_subtract, 0, 0, 1)
    261   ZEND_ARG_INFO(0, timeval)
    262 ZEND_END_ARG_INFO()
    263 
    264 ZEND_BEGIN_ARG_INFO_EX(arginfo_zero, 0, 0, 0)
    265 ZEND_END_ARG_INFO()
    266 
    267 static zend_function_entry timeval_methods[] = {
    268   PHP_ME(Timeval, __construct, arginfo_construct,
    269          ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
    270   PHP_ME(Timeval, add, arginfo_add,
    271          ZEND_ACC_PUBLIC)
    272   PHP_ME(Timeval, compare, arginfo_compare,
    273          ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
    274   PHP_ME(Timeval, infFuture, arginfo_infFuture,
    275          ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
    276   PHP_ME(Timeval, infPast, arginfo_infPast,
    277          ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
    278   PHP_ME(Timeval, now, arginfo_now,
    279          ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
    280   PHP_ME(Timeval, similar, arginfo_similar,
    281          ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
    282   PHP_ME(Timeval, sleepUntil, arginfo_sleepUntil,
    283          ZEND_ACC_PUBLIC)
    284   PHP_ME(Timeval, subtract, arginfo_subtract,
    285          ZEND_ACC_PUBLIC)
    286   PHP_ME(Timeval, zero, arginfo_zero,
    287          ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
    288   PHP_FE_END
    289 };
    290 
    291 void grpc_init_timeval(TSRMLS_D) {
    292   zend_class_entry ce;
    293   INIT_CLASS_ENTRY(ce, "Grpc\\Timeval", timeval_methods);
    294   ce.create_object = create_wrapped_grpc_timeval;
    295   grpc_ce_timeval = zend_register_internal_class(&ce TSRMLS_CC);
    296   PHP_GRPC_INIT_HANDLER(wrapped_grpc_timeval, timeval_ce_handlers);
    297 }
    298 
    299 void grpc_shutdown_timeval(TSRMLS_D) {}
    300