#include <string.h>
#include <unistd.h>
#include <errno.h>
+#include <time.h>
#include <glib.h>
#include <system_info.h>
#include <system_settings.h>
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)
{
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);
{
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);
}
{
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);
+}
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__ */
#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()
{
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();
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;
}
static int icl_timeout_seconds = ICL_TIMEOUT_DEFAULT;
static int icl_init_count;
-API int iotcon_initialize()
+API int iotcon_initialize(void)
{
int ret;
*
* @see iotcon_deinitialize()
*/
-int iotcon_initialize();
+int iotcon_initialize(void);
/**
* @brief Deinitializes from the iotcon service.
*/
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);
+
/**
* @}
*/