Add APIs for polling 58/67258/18
authoryoungman <yman.jung@samsung.com>
Tue, 26 Apr 2016 05:18:54 +0000 (14:18 +0900)
committeryoungman <yman.jung@samsung.com>
Fri, 20 May 2016 02:09:17 +0000 (11:09 +0900)
Change-Id: I66530fd487a3345183acbcc2f022965033726912
Signed-off-by: youngman <yman.jung@samsung.com>
common/ic-utils.c
common/ic-utils.h
lib/icl-ioty-ocprocess.c
lib/icl.c
lib/include/iotcon.h

index 952fb937a0a04f18008f4b6601b74997f6f93b81..6d7b79a02b26d467ea2b8c7375dbc0e778c23f44 100644 (file)
@@ -17,6 +17,7 @@
 #include <string.h>
 #include <unistd.h>
 #include <errno.h>
+#include <time.h>
 #include <glib.h>
 #include <system_info.h>
 #include <system_settings.h>
@@ -52,10 +53,12 @@ static const char *IC_SYSTEM_INFO_MODEL_NAME = "http://tizen.org/system/model_na
 static const char *IC_SYSTEM_INFO_BUILD_STRING = "http://tizen.org/system/build.string";
 static const char *IC_SYSTEM_INFO_TIZEN_ID = "http://tizen.org/system/tizenid";
 
-static pthread_mutex_t icl_utils_mutex_init = PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t icl_utils_mutex_ioty = PTHREAD_MUTEX_INITIALIZER;
-static __thread int icl_utils_pthread_oldstate;
-static __thread int icl_utils_mutex_count;
+static pthread_mutex_t ic_utils_mutex_init = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t ic_utils_mutex_ioty = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t ic_utils_mutex_polling = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t ic_utils_cond_polling;
+static __thread int ic_utils_pthread_oldstate;
+static __thread int ic_utils_mutex_count;
 
 char* ic_utils_strdup(const char *src)
 {
@@ -220,10 +223,13 @@ static inline pthread_mutex_t* _utils_mutex_get(int type)
 
        switch (type) {
        case IC_UTILS_MUTEX_INIT:
-               mutex = &icl_utils_mutex_init;
+               mutex = &ic_utils_mutex_init;
                break;
        case IC_UTILS_MUTEX_IOTY:
-               mutex = &icl_utils_mutex_ioty;
+               mutex = &ic_utils_mutex_ioty;
+               break;
+       case IC_UTILS_MUTEX_POLLING:
+               mutex = &ic_utils_mutex_polling;
                break;
        default:
                ERR("Invalid type(%d)", type);
@@ -237,9 +243,9 @@ void ic_utils_mutex_lock(int type)
 {
        int ret;
 
-       icl_utils_mutex_count++;
-       if (1 == icl_utils_mutex_count) {
-               ret = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &icl_utils_pthread_oldstate);
+       ic_utils_mutex_count++;
+       if (1 == ic_utils_mutex_count) {
+               ret = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &ic_utils_pthread_oldstate);
                WARN_IF(0 != ret, "pthread_setcancelstate() Fail(%d)", ret);
        }
 
@@ -251,12 +257,88 @@ void ic_utils_mutex_unlock(int type)
 {
        int ret;
 
-       icl_utils_mutex_count--;
-       if (0 == icl_utils_mutex_count) {
-               ret = pthread_setcancelstate(icl_utils_pthread_oldstate, NULL);
+       ic_utils_mutex_count--;
+       if (0 == ic_utils_mutex_count) {
+               ret = pthread_setcancelstate(ic_utils_pthread_oldstate, NULL);
                WARN_IF(0 != ret, "pthread_setcancelstate() Fail(%d)", ret);
        }
 
        ret = pthread_mutex_unlock(_utils_mutex_get(type));
        WARN_IF(0 != ret, "pthread_mutex_unlock() Fail(%d)", ret);
 }
+
+int ic_utils_cond_polling_init()
+{
+       FN_CALL;
+       int ret;
+       pthread_condattr_t attr;
+
+       ret = pthread_condattr_init(&attr);
+       if (0 != ret) {
+               ERR("pthread_condattr_init() Fail(%d)", ret);
+               pthread_condattr_destroy(&attr);
+               return IOTCON_ERROR_SYSTEM;
+       }
+
+       ret = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
+       if (0 != ret) {
+               ERR("pthread_condattr_setclock() Fail(%d)", ret);
+               pthread_condattr_destroy(&attr);
+               return IOTCON_ERROR_SYSTEM;
+       }
+
+       ret = pthread_cond_init(&ic_utils_cond_polling, &attr);
+       if (0 != ret) {
+               ERR("pthread_cond_init() Fail(%d)", ret);
+               pthread_condattr_destroy(&attr);
+               return IOTCON_ERROR_SYSTEM;
+       }
+
+       pthread_condattr_destroy(&attr);
+
+       return IOTCON_ERROR_NONE;
+}
+
+void ic_utils_cond_polling_destroy()
+{
+       pthread_cond_destroy(&ic_utils_cond_polling);
+}
+
+static inline pthread_cond_t* _utils_cond_get(int type)
+{
+       pthread_cond_t *cond;
+
+       if (IC_UTILS_COND_POLLING == type) {
+               cond = &ic_utils_cond_polling;
+       } else {
+               ERR("Invalid type(%d)", type);
+               cond = NULL;
+       }
+
+       return cond;
+}
+
+void ic_utils_cond_signal(int type)
+{
+       int ret;
+
+       ret = pthread_cond_signal(_utils_cond_get(type));
+       WARN_IF(0 != ret, "pthread_cond_signal() Fail(%d)", ret);
+}
+
+void ic_utils_cond_timedwait(int cond_type, int mutex_type, int polling_interval)
+{
+       int ret, nsec;
+       struct timespec ts;
+
+       clock_gettime(CLOCK_MONOTONIC, &ts);
+
+       /* ts.tv_nsec exists between 0 and 1000000000 */
+       nsec = (polling_interval % 1000) * 1000000;
+       ts.tv_sec = (polling_interval / 1000) + (nsec / 1000000000);
+       ts.tv_nsec = nsec % 1000000000;
+
+       ret = pthread_cond_timedwait(_utils_cond_get(cond_type), _utils_mutex_get(mutex_type),
+                       &ts);
+       WARN_IF(ETIMEDOUT != ret && 0 != ret, "pthread_cond_timedwait() Fail(%d)", ret);
+}
index 6e52ff77e9efdf2d2dd1ce3f0e5d296d696bb526..a69344a19ce47bae541ad5c56bd823f12d051ff6 100644 (file)
@@ -35,10 +35,22 @@ void ic_utils_free_platform_info(OCPlatformInfo *platform_info);
 void ic_utils_mutex_lock(int type);
 void ic_utils_mutex_unlock(int type);
 
+int ic_utils_cond_polling_init();
+void ic_utils_cond_polling_destroy();
+
+void ic_utils_cond_signal(int type);
+void ic_utils_cond_timedwait(int cond_type, int mutex_type, int polling_interval);
+
 enum IC_UTILS_MUTEX {
        IC_UTILS_MUTEX_INIT,
        IC_UTILS_MUTEX_IOTY,
+       IC_UTILS_MUTEX_POLLING,
        IC_UTILS_MUTEX_MAX
 };
 
+enum IC_UTILS_COND {
+       IC_UTILS_COND_POLLING,
+       IC_UTILS_COND_MAX
+};
+
 #endif /* __IOT_CONNECTIVITY_INTERNAL_COMMON_UTILITY_H__ */
index a99401627c5b836a291003266d624f8e7e28f0d2..d19a942610e0a6c9465c32f6dfc6c0ea7ba1ceca 100644 (file)
@@ -16,7 +16,6 @@
 #include <stdlib.h>
 #include <errno.h>
 #include <sys/prctl.h>
-
 #include <ocstack.h>
 #include <octypes.h>
 
 #include "icl-ioty-types.h"
 #include "icl-ioty-ocprocess.h"
 
+#define ICL_IOTY_TIME_INTERVAL_MIN 0
+#define ICL_IOTY_TIME_INTERVAL_DEFAULT 100
+
 static int icl_ioty_alive = 1;
+static int icl_ioty_polling_interval;
 
 void icl_ioty_ocprocess_stop()
 {
@@ -52,18 +55,65 @@ void icl_ioty_ocprocess_start()
        icl_ioty_alive = 1;
 }
 
+
+API int iotcon_polling_get_interval(int *interval)
+{
+       RETV_IF(false == ic_utils_check_oic_feature_supported(), IOTCON_ERROR_NOT_SUPPORTED);
+       RETV_IF(NULL == interval, IOTCON_ERROR_INVALID_PARAMETER);
+
+       *interval = icl_ioty_polling_interval;
+
+       return IOTCON_ERROR_NONE;
+}
+
+
+API int iotcon_polling_set_interval(int interval)
+{
+       RETV_IF(false == ic_utils_check_oic_feature_supported(), IOTCON_ERROR_NOT_SUPPORTED);
+       RETV_IF(interval <= ICL_IOTY_TIME_INTERVAL_MIN, IOTCON_ERROR_INVALID_PARAMETER);
+
+       icl_ioty_polling_interval = interval;
+
+       ic_utils_mutex_lock(IC_UTILS_MUTEX_POLLING);
+       ic_utils_cond_signal(IC_UTILS_COND_POLLING);
+       ic_utils_mutex_unlock(IC_UTILS_MUTEX_POLLING);
+
+       return IOTCON_ERROR_NONE;
+}
+
+
+API int iotcon_polling_invoke(void)
+{
+       RETV_IF(false == ic_utils_check_oic_feature_supported(), IOTCON_ERROR_NOT_SUPPORTED);
+
+       ic_utils_mutex_lock(IC_UTILS_MUTEX_POLLING);
+       ic_utils_cond_signal(IC_UTILS_COND_POLLING);
+       ic_utils_mutex_unlock(IC_UTILS_MUTEX_POLLING);
+
+       return IOTCON_ERROR_NONE;
+}
+
+
 void* icl_ioty_ocprocess_thread(void *data)
 {
        FN_CALL;
        int ret;
        OCStackResult result;
-       const struct timespec delay = {0, 10 * 1000 * 1000}; /* 10 ms */
+
+       // TODO: Current '100ms' is not proven sleep time. Revise the time after test.
+       // TODO: Or recommend changes to event driven architecture
+       icl_ioty_polling_interval = ICL_IOTY_TIME_INTERVAL_DEFAULT;
 
        /* For setting this thread name */
        ret = prctl(PR_SET_NAME, "iotcon_ocprocess_thread");
        if (0 != ret)
                ERR("prctl(PR_SET_NAME) Fail(%d)", ret);
 
+       ret = ic_utils_cond_polling_init();
+       if (IOTCON_ERROR_NONE != ret)
+               ERR("ic_utils_cond_polling_init() Fail(%d)", ret);
+
+       ic_utils_mutex_lock(IC_UTILS_MUTEX_POLLING);
        while (icl_ioty_alive) {
                ic_utils_mutex_lock(IC_UTILS_MUTEX_IOTY);
                result = OCProcess();
@@ -73,10 +123,12 @@ void* icl_ioty_ocprocess_thread(void *data)
                        break;
                }
 
-               // TODO: Current '10ms' is not proven sleep time. Revise the time after test.
-               // TODO: Or recommend changes to event driven architecture
-               nanosleep(&delay, NULL);
+               ic_utils_cond_timedwait(IC_UTILS_COND_POLLING, IC_UTILS_MUTEX_POLLING,
+                               icl_ioty_polling_interval);
        }
+       ic_utils_mutex_unlock(IC_UTILS_MUTEX_POLLING);
+
+       ic_utils_cond_polling_destroy();
 
        return NULL;
 }
index d6d57aaa5870f5cb415b1555f29f525c8096ee3a..e80ffced54e879e4da5539ecee6553e39612b898 100644 (file)
--- a/lib/icl.c
+++ b/lib/icl.c
@@ -27,7 +27,7 @@ static pthread_t icl_thread;
 static int icl_timeout_seconds = ICL_TIMEOUT_DEFAULT;
 static int icl_init_count;
 
-API int iotcon_initialize()
+API int iotcon_initialize(void)
 {
        int ret;
 
index 9250b3a1c6b038694266c23acf842aa0746761d3..592c80969573d152fb00b4029877656078cb01f6 100644 (file)
@@ -66,7 +66,7 @@ extern "C" {
  *
  * @see iotcon_deinitialize()
  */
-int iotcon_initialize();
+int iotcon_initialize(void);
 
 /**
  * @brief Deinitializes from the iotcon service.
@@ -127,6 +127,63 @@ int iotcon_get_timeout(int *timeout_seconds);
  */
 int iotcon_set_timeout(int timeout_seconds);
 
+/**
+ * @brief Gets the polling interval(milliseconds) of IoTCon.
+ * @details This API gets the polling interval of IoTCon.
+ * Default polling interval is 100 milliseconds.
+ *
+ * @since_tizen 3.0
+ *
+ * @param[out] interval Milliseconds for polling interval
+ *
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #IOTCON_ERROR_NONE Successful
+ * @retval #IOTCON_ERROR_NOT_SUPPORTED  Not supported
+ * @retval #IOTCON_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @pre iotcon_initialize() should be called to initialize.
+ *
+ * @see iotcon_set_timeout()
+ */
+int iotcon_polling_get_interval(int *interval);
+
+/**
+ * @brief Sets the polling interval(milliseconds) of IoTCon.
+ * @details This API sets the polling interval of IoTCon.
+ * The closer to 0, the faster it operates. It is invoked immediately for changing the interval.
+ * Default polling interval is 100 milliseconds. If you want the faster operation,
+ * we recommend you set 10 milliseconds for polling interval.
+ *
+ * @since_tizen 3.0
+ *
+ * @param[in] interval Milliseconds for polling interval (must be in range from 1 to 999)
+ *
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #IOTCON_ERROR_NONE Successful
+ * @retval #IOTCON_ERROR_NOT_SUPPORTED  Not supported
+ * @retval #IOTCON_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @pre iotcon_initialize() should be called to initialize.
+ *
+ * @see iotcon_polling_get_interval()
+ */
+int iotcon_polling_set_interval(int interval);
+
+/**
+ * @brief Invokes a next message from a queue for receiving messages from others, immediately.
+ * @details This API invokes a next message from a queue for receiving messages from others, immediately.\n
+ * After calling the API, it continues the polling with existing interval.
+ *
+ * @since_tizen 3.0
+ *
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #IOTCON_ERROR_NONE Successful
+ * @retval #IOTCON_ERROR_NOT_SUPPORTED  Not supported
+ *
+ * @pre iotcon_initialize() should be called to initialize.
+ */
+int iotcon_polling_invoke(void);
+
 /**
  * @}
  */