mirror of
https://github.com/stefanocasazza/ULib.git
synced 2025-09-28 19:05:55 +08:00
467 lines
8.4 KiB
C++
467 lines
8.4 KiB
C++
// test_notifier.cpp
|
|
|
|
#include <ulib/file.h>
|
|
#include <ulib/timer.h>
|
|
#include <ulib/notifier.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
struct node {
|
|
node* next;
|
|
int data;
|
|
static node* first;
|
|
};
|
|
|
|
node* node::first;
|
|
|
|
static void list_add(int i)
|
|
{
|
|
node* n = (node*)malloc(sizeof(node));
|
|
|
|
n->data = i;
|
|
n->next = node::first;
|
|
|
|
node::first = n;
|
|
}
|
|
|
|
static void list_print()
|
|
{
|
|
printf("print list\n");
|
|
|
|
for (node* n = node::first; n; n = n->next)
|
|
{
|
|
printf("list: %p %p %d\n", n, n->next, n->data);
|
|
}
|
|
|
|
fflush(stdout);
|
|
}
|
|
|
|
static void list_destroy()
|
|
{
|
|
printf("destroy list\n");
|
|
|
|
node* prev = U_NULLPTR;
|
|
|
|
for (node* n = node::first; n; prev = n, n = n->next)
|
|
{
|
|
if (prev) free(prev);
|
|
}
|
|
|
|
if (prev) free(prev);
|
|
|
|
node::first = U_NULLPTR;
|
|
}
|
|
|
|
static void list_creat()
|
|
{
|
|
list_add(0); /* list: 0 */
|
|
list_add(1); /* list: 1 0 */
|
|
list_add(2); /* list: 2 1 0 */
|
|
list_add(3); /* list: 3 2 1 0 */
|
|
list_add(4); /* list: 4 3 2 1 0 */
|
|
}
|
|
|
|
static void list_remove(node** ptr)
|
|
{
|
|
node* item = *ptr;
|
|
|
|
*ptr = item->next;
|
|
|
|
printf("remove %d\n", item->data);
|
|
|
|
free(item);
|
|
}
|
|
|
|
static void list_test()
|
|
{
|
|
list_creat();
|
|
list_print();
|
|
|
|
// this is WRONG...
|
|
|
|
printf("*****WRONG************\n");
|
|
|
|
node* item;
|
|
node** ptr;
|
|
|
|
for (ptr = &node::first; (item = *ptr); ptr = &(*ptr)->next)
|
|
{
|
|
printf("item: %p %p %d\n", item, item->next, item->data);
|
|
|
|
if (item->data == 2) list_remove(ptr);
|
|
}
|
|
|
|
list_print();
|
|
|
|
printf("**********************\n");
|
|
|
|
// this is WRONG...
|
|
|
|
list_destroy();
|
|
list_creat();
|
|
list_print();
|
|
|
|
printf("*****WRONG************\n");
|
|
|
|
item = node::first;
|
|
ptr = &node::first;
|
|
|
|
do {
|
|
printf("item: %p %p %d\n", item, item->next, item->data);
|
|
|
|
if (item->data == 2) list_remove(ptr);
|
|
|
|
ptr = &(*ptr)->next;
|
|
}
|
|
while ((item = *ptr));
|
|
|
|
list_print();
|
|
|
|
printf("**********************\n");
|
|
|
|
// this is WRONG...
|
|
|
|
list_destroy();
|
|
list_creat();
|
|
list_print();
|
|
|
|
printf("*****WRONG************\n");
|
|
|
|
ptr = &node::first;
|
|
|
|
while ((item = *ptr))
|
|
{
|
|
printf("item: %p %p %d\n", item, item->next, item->data);
|
|
|
|
if (item->data == 3) list_remove(ptr);
|
|
|
|
ptr = &(*ptr)->next;
|
|
}
|
|
|
|
list_print();
|
|
|
|
printf("**********************\n");
|
|
|
|
// this is OK...
|
|
|
|
list_destroy();
|
|
list_creat();
|
|
list_print();
|
|
|
|
printf("*****OK***************\n");
|
|
|
|
ptr = &node::first;
|
|
|
|
while ((item = *ptr))
|
|
{
|
|
printf("item: %p %p %d\n", item, item->next, item->data);
|
|
|
|
if (item->data == 3)
|
|
{
|
|
list_remove(ptr);
|
|
|
|
continue;
|
|
}
|
|
|
|
ptr = &(*ptr)->next;
|
|
}
|
|
|
|
list_print();
|
|
|
|
printf("**********************\n");
|
|
|
|
// this is OK...
|
|
|
|
list_destroy();
|
|
list_creat();
|
|
list_print();
|
|
|
|
printf("*****OK***************\n");
|
|
|
|
item = node::first;
|
|
ptr = &node::first;
|
|
|
|
do {
|
|
printf("item: %p %p %d\n", item, item->next, item->data);
|
|
|
|
if (item->data == 2)
|
|
{
|
|
list_remove(ptr);
|
|
|
|
continue;
|
|
}
|
|
|
|
ptr = &(*ptr)->next;
|
|
}
|
|
while ((item = *ptr));
|
|
|
|
list_print();
|
|
|
|
printf("**********************\n");
|
|
|
|
exit(0);
|
|
}
|
|
|
|
class MyAlarm1 : public UEventTime {
|
|
public:
|
|
|
|
// COSTRUTTORI
|
|
|
|
MyAlarm1(long sec, long usec) : UEventTime(sec, usec)
|
|
{
|
|
U_TRACE_CTOR(0, MyAlarm1, "%ld,%ld", sec, usec)
|
|
}
|
|
|
|
~MyAlarm1()
|
|
{
|
|
U_TRACE_DTOR(0, MyAlarm1)
|
|
}
|
|
|
|
virtual int handlerTime()
|
|
{
|
|
U_TRACE(0, "MyAlarm1::handlerTime()")
|
|
|
|
// return value:
|
|
// ---------------
|
|
// -1 - normal
|
|
// 0 - monitoring
|
|
// ---------------
|
|
|
|
U_RETURN(-1);
|
|
}
|
|
|
|
#if defined(U_STDCPP_ENABLE) && defined(DEBUG)
|
|
const char* dump(bool _reset) const { return UEventTime::dump(_reset); }
|
|
#endif
|
|
};
|
|
|
|
class MyAlarm2 : public MyAlarm1 {
|
|
public:
|
|
|
|
// COSTRUTTORI
|
|
|
|
MyAlarm2(long sec, long usec) : MyAlarm1(sec, usec)
|
|
{
|
|
U_TRACE_CTOR(0, MyAlarm2, "%ld,%ld", sec, usec)
|
|
}
|
|
|
|
~MyAlarm2()
|
|
{
|
|
U_TRACE_DTOR(0, MyAlarm2)
|
|
}
|
|
|
|
virtual int handlerTime()
|
|
{
|
|
U_TRACE(0, "MyAlarm2::handlerTime()")
|
|
|
|
// return value:
|
|
// ---------------
|
|
// -1 - normal
|
|
// 0 - monitoring
|
|
// ---------------
|
|
|
|
U_RETURN(0);
|
|
}
|
|
|
|
#if defined(U_STDCPP_ENABLE) && defined(DEBUG)
|
|
const char* dump(bool _reset) const { return MyAlarm1::dump(_reset); }
|
|
#endif
|
|
};
|
|
|
|
static char message[4096];
|
|
static int _i, fd_input, fd_output;
|
|
|
|
class handlerOutput : public UEventFd {
|
|
public:
|
|
|
|
handlerOutput()
|
|
{
|
|
fd = fd_output;
|
|
op_mask = EPOLLOUT;
|
|
}
|
|
|
|
~handlerOutput()
|
|
{
|
|
}
|
|
|
|
int handlerWrite()
|
|
{
|
|
U_TRACE(0, "handlerOutput::handlerWrite()")
|
|
|
|
# ifdef U_STDCPP_ENABLE
|
|
cout << "receive message: " << message << endl;
|
|
# endif
|
|
|
|
U_RETURN(0);
|
|
}
|
|
|
|
#if defined(U_STDCPP_ENABLE) && defined(DEBUG)
|
|
const char* dump(bool _reset) const
|
|
{
|
|
*UObjectIO::os << "fd " << fd << "\n"
|
|
<< "op_mask " << op_mask;
|
|
|
|
if (_reset)
|
|
{
|
|
UObjectIO::output();
|
|
|
|
return UObjectIO::buffer_output;
|
|
}
|
|
|
|
return U_NULLPTR;
|
|
}
|
|
#endif
|
|
};
|
|
|
|
class handlerInput : public UEventFd {
|
|
public:
|
|
|
|
handlerInput()
|
|
{
|
|
fd = fd_input;
|
|
}
|
|
|
|
~handlerInput()
|
|
{
|
|
}
|
|
|
|
int handlerRead()
|
|
{
|
|
U_TRACE(0, "handlerInput::handlerRead()")
|
|
|
|
int bytes_read = U_SYSCALL(read, "%d,%p,%u", fd, message, 13);
|
|
|
|
if (bytes_read > 0)
|
|
{
|
|
if (_i & 1)
|
|
{
|
|
if (UNotifier::waitForWrite(fd_output) >= 1)
|
|
{
|
|
static handlerOutput* handler_output;
|
|
|
|
if (handler_output == U_NULLPTR)
|
|
{
|
|
U_NEW_WITHOUT_CHECK_MEMORY(handlerOutput, handler_output, handlerOutput);
|
|
|
|
UNotifier::insert(handler_output);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
U_RETURN(0);
|
|
}
|
|
|
|
#if defined(U_STDCPP_ENABLE) && defined(DEBUG)
|
|
const char* dump(bool _reset) const
|
|
{
|
|
*UObjectIO::os << "fd " << fd << "\n"
|
|
<< "op_mask " << op_mask;
|
|
|
|
if (_reset)
|
|
{
|
|
UObjectIO::output();
|
|
|
|
return UObjectIO::buffer_output;
|
|
}
|
|
|
|
return U_NULLPTR;
|
|
}
|
|
#endif
|
|
};
|
|
|
|
int U_EXPORT main(int argc, char* argv[])
|
|
{
|
|
U_ULIB_INIT(argv);
|
|
|
|
U_TRACE(5,"main(%d)",argc)
|
|
|
|
list_test();
|
|
|
|
int fds[2], n = (argc > 1 ? u_atoi(argv[1]) : 5);
|
|
|
|
pipe(fds);
|
|
|
|
// fd_input = U_SYSCALL(open, "%S,%d", "inp/notifier.input", O_RDONLY); // STDIN_FILENO
|
|
// fd_output = U_SYSCALL(open, "%S,%d,%d", "tmp/notifier.output", O_WRONLY | O_CREAT, PERM_FILE); // STDOUT_FILENO
|
|
|
|
// fds[0] is for READING, fds[1] is for WRITING
|
|
|
|
fd_input = fds[0];
|
|
fd_output = fds[1];
|
|
|
|
handlerInput* c;
|
|
handlerInput* d;
|
|
|
|
U_NEW_WITHOUT_CHECK_MEMORY(handlerInput, c, handlerInput);
|
|
U_NEW_WITHOUT_CHECK_MEMORY(handlerInput, d, handlerInput);
|
|
|
|
UNotifier::init();
|
|
UNotifier::insert(c);
|
|
UNotifier::handlerDelete(c);
|
|
UNotifier::insert(d);
|
|
|
|
#ifdef __unix__
|
|
U_ASSERT(UNotifier::waitForRead( fds[0], 500) <= 0)
|
|
#endif
|
|
U_ASSERT(UNotifier::waitForWrite(fds[1], 500) >= 1)
|
|
|
|
MyAlarm1* a;
|
|
MyAlarm2* b;
|
|
|
|
U_NEW_WITHOUT_CHECK_MEMORY(MyAlarm1, a, MyAlarm1(1L, 0L));
|
|
U_NEW_WITHOUT_CHECK_MEMORY(MyAlarm2, b, MyAlarm2(1L, 0L));
|
|
|
|
UTimer::init(UTimer::ASYNC);
|
|
|
|
UTimer::insert(a);
|
|
UTimer::insert(b);
|
|
|
|
UTimer::setTimer();
|
|
|
|
#if defined(U_STDCPP_ENABLE) && defined(DEBUG)
|
|
if (argc > 2) UTimer::printInfo(cout);
|
|
#endif
|
|
|
|
UEventTime timeout;
|
|
|
|
for (_i = 0; _i < n; ++_i)
|
|
{
|
|
timeout.setMicroSecond(100L * 1000L);
|
|
|
|
(void) U_SYSCALL(write, "%d,%p,%u", fd_output, U_CONSTANT_TO_PARAM("hello, world"));
|
|
|
|
UNotifier::waitForEvent(&timeout);
|
|
(void) UNotifier::waitForRead(fds[0], 500);
|
|
|
|
U_NEW_WITHOUT_CHECK_MEMORY(MyAlarm1, a, MyAlarm1(1L, 0L));
|
|
|
|
UTimer::insert(a);
|
|
|
|
UTimer::setTimer();
|
|
|
|
timeout.nanosleep();
|
|
|
|
# if defined(U_STDCPP_ENABLE) && defined(DEBUG)
|
|
if (argc > 2) UTimer::printInfo(cout);
|
|
# endif
|
|
}
|
|
|
|
#if defined(U_STDCPP_ENABLE) && defined(DEBUG)
|
|
if (argc > 2) UTimer::printInfo(cout);
|
|
#endif
|
|
|
|
UTimer::clear();
|
|
|
|
#if defined(U_STDCPP_ENABLE) && defined(DEBUG)
|
|
if (argc > 2) UTimer::printInfo(cout);
|
|
#endif
|
|
|
|
UNotifier::clear();
|
|
|
|
#ifdef __unix__
|
|
U_ASSERT(UNotifier::waitForRead( fd_input, 1 * 1000) <= 0)
|
|
#endif
|
|
U_ASSERT(UNotifier::waitForWrite(fd_output, 1 * 1000) >= 1)
|
|
}
|