ווטסאפ - לינוקס, BSD, קוד פתוח ותוכנה חופשית בעברית. Whatsup - Linux, BSD, open source and free software in Hebrew

 
 
  כניסת חברים · רישום · שכחתי סיסמה  
tux the penguin
תגובה לנושא
צפיה בנושא הבא Printable version התחבר כדי לבדוק הודעות פרטיות צפיה בנושא הקודם
elcucoלא בפורום כעת ת.הצטרפות: 14/10/2003 · הודעות: 6258 ·
 

הודעה פורסם: 02/05/2023 - 18:32
נושא ההודעה: אלטרנטיבה עבור Posix timers

אני מנסה לעשות timer ב־posix. מצאתי את
קוד:
timer_settime
והוא די עובד ומספק את הסחורה, למעט... כשאתה מפעיל את התוכנה תחת gdb מתקבל סיגנל וזה מקריס את התוכנה ואת gdb.

הפתרון הוא להוסיף כמה הגדרות ל־gdb כמתואר כאן: https://itecnote.com/tecnote/linux-program-terminating-on-receiving-signal-sig34-real-time-event-34/

... אבל לא בא לי בטוב. אני מחפש api אחר שאני אוכל להשתמש בו, כדי ליצור כמה timers - ושאוכל לחבר כל אחד אל
קוד:
std::function
אחר.

מה ההצעות? (בבקשה הצעות low level ללא frameworks כמו Qt או GTK).

הקוד שלי הוא:
קוד:


struct Timer {
    std::function<void()> callback;
    int64_t millies;
    bool repeating;

    Timer();
    auto start() -> void;

  private:
    static auto handler(int sig, siginfo_t *si, void *uc) -> void;

    struct sigaction sa;
    struct sigevent sev;
    struct itimerspec its;
    timer_t timerid;
};

Timer::Timer() {

    sa.sa_flags = SA_SIGINFO;
    sa.sa_sigaction = handler;
    sigemptyset(&sa.sa_mask);
    if (sigaction(SIGRTMIN, &sa, NULL) == -1) {
        // errExit("sigaction");
        return;
    }

    sev.sigev_notify = SIGEV_SIGNAL;
    sev.sigev_signo = SIGRTMIN;
    sev.sigev_value.sival_ptr = &timerid;
    sev.sigev_value.sival_ptr = this;
    if (timer_create(CLOCK_REALTIME, &sev, &timerid) == -1) {
        // assert("timer_create");
        return;
    }
}

auto Timer::start() -> void {
    its.it_value.tv_sec = millies / 1000;
    its.it_value.tv_nsec = millies % 1000;
    its.it_interval.tv_sec = its.it_value.tv_sec;
    its.it_interval.tv_nsec = its.it_value.tv_nsec;
    if (timer_settime(timerid, 0, &its, NULL) == -1) {
        // error
    }
}

auto Timer::handler(int sig, siginfo_t *si, void *uc) -> void {
    Timer *timer = static_cast<Timer *>(si->si_value.sival_ptr);
    timer->callback();
}


...
int main() {
    Timer t1;
    t1.millies = 2000;
    t1.callback = [&i, &logger]() {
        i++;
        logger->info("Timer");
    };

    // or some other blocking function
    while (1) {};
    return ;
};
 
 צפיה בפרופיל המשתמש שלח הודעה פרטית  
תגובה  עם ציטוט חזרה למעלה
חזרה לתוכן הדיון
elcucoלא בפורום כעת ת.הצטרפות: 14/10/2003 · הודעות: 6258 ·
 

הודעה פורסם: 02/05/2023 - 18:37
נושא ההודעה:

ליידע כללי, שאלתי את chat GPT בנושא, והוא הציע לעשות std::thread ובו לעשות לולאה, לחכות ואז לקרא לפונקציה שלי. זה בהחלט יעבוד, אבל מאוד לא חסכוני במשאבים - להרים thread עבור כל timer זה מאוד לא יעיל.

קוד:

#include <iostream>
#include <chrono>
#include <atomic>
#include <thread>

std::atomic<bool> stop_flag(false);

void timer_callback()
{
    std::cout << "Timer callback\n";
}

void start_timer(int interval, std::function<void()> callback)
{
    while (!stop_flag.load())
    {
        std::chrono::milliseconds timespan(interval);
        std::this_thread::sleep_for(timespan);
        callback();
    }
}

int main()
{
    std::thread timer_thread(start_timer, 1000, timer_callback);
   
    // Do some other work here
    // ...

    // Stop the timer thread
    stop_flag.store(true);
    timer_thread.join();
   
    return 0;
}
 
 צפיה בפרופיל המשתמש שלח הודעה פרטית  
תגובה  עם ציטוט חזרה למעלה
חזרה לתוכן הדיון
elcucoלא בפורום כעת ת.הצטרפות: 14/10/2003 · הודעות: 6258 ·
 

הודעה פורסם: 03/05/2023 - 08:37
נושא ההודעה:

מימוש שעובד (עברתי לקבל הודעה ב־thread במקום סיגנל, וזה מתנהג יותר טוב וגם מצריך פחות setup):

קוד:

auto Timer::start() -> void {
    struct sigevent sev;
    memset(&sev, 0, sizeof sev);
    sev.sigev_notify = SIGEV_THREAD;
    sev.sigev_notify_function = &Timer::handler;
    sev.sigev_value.sival_ptr = this;
    timer_t timerid = 0;
    int ret = timer_create(CLOCK_MONOTONIC, &sev, &timerid);
    if (ret) {
        ret = errno;
        exit(1);
    }

    // Arm the timer to expire in the specified interval.
    struct itimerspec trigger;
    memset(&trigger, 0, sizeof trigger);
    trigger.it_value.tv_sec = millies / 1000;
    trigger.it_value.tv_nsec = millies % 1000;
    trigger.it_interval.tv_sec = trigger.it_value.tv_sec;
    trigger.it_interval.tv_nsec = trigger.it_value.tv_nsec;
    ret = timer_settime(timerid, 0, &trigger, NULL);
    if (ret) {
        ret = errno;
        exit(1);
    }
}

auto Timer::handler(sigval sival_int) -> void {
    Timer *timer = static_cast<Timer *>(sival_int.sival_ptr);
    timer->callback();
}


מעניין כמה זה עובד ב־osx... אין לי אפשרות לבדוק Smile
 
 צפיה בפרופיל המשתמש שלח הודעה פרטית  
תגובה  עם ציטוט חזרה למעלה
חזרה לתוכן הדיון
אורח · ·
 

הודעה פורסם: 03/05/2023 - 15:42
נושא ההודעה: לא חושב שניתן להבטחי אותו thread גם ב std::async

לא חושב שניתן להבטחי אותו thread גם ב std::async הוא מחליט לבד ומעדיף thread נפרד

מה שנישמע לי שאנחנו מחפשים זה סיגנלים וסלוטים.
כאשר השעון רץ ס thread אחד ווה- סלוטים עונים לו באחר.

זה ניראה לי ממש מורכב לעשות דבר כזה, ולכן עדיף כבר לקחת מ Boost.

לא הצלחתי להריץ אץ מש ששמתה - לא הבנתי איך לכתוב את זה ב- main()

# יכול להיות שאני ממש טועה,

אם ניתן להבטיח ב c++ שזה ירוץ ויחקה על אותו thread כמו ב Javascript
 
   
תגובה  עם ציטוט חזרה למעלה
חזרה לתוכן הדיון
אורח · ·
 

הודעה פורסם: 03/05/2023 - 15:54
נושא ההודעה: time.h לא מכיל את כל ההגדרות כמו בלינוקס וזה לא מתקמפל

```
[build] /Volumes/RAM_Disk_4G/f/main.cpp:37:23: error: field has incomplete type 'struct itimerspec'
[build] struct itimerspec its;
[build] ^
```

הדרך הכי נכונה היא לבחון איך boost עושה את זה,

https://www.boost.org/doc/libs/1_66_0/doc/html/boost_asio/tutorial/tuttimer2.html
 
   
תגובה  עם ציטוט חזרה למעלה
חזרה לתוכן הדיון
אורח · ·
 

הודעה פורסם: 03/05/2023 - 16:10
נושא ההודעה: כשאני חושב על זה - יש חשיבות למה שאתה מנשה לעשות

אם נניח ויש לך כרטיס קול מיותר - או אפילו עם חיבור WC (קואקס) לשעון אטומי

אז אולי נכון לייצר טיימר זמן אמת עבור המחשב, ואז נוכל לסנכרן דברים על ספירה של
frames.

ואת ההבקשות וההוראות הוא ייתן ויקבל מ devices of mkfifo.

אין סיבה שב 2023 כשהעולם כולכך מתקדם, מחשב אישי לא יעבוד עם זמן אמת אמיתי.....
 
   
תגובה  עם ציטוט חזרה למעלה
חזרה לתוכן הדיון
אורח · ·
 

הודעה פורסם: 04/05/2023 - 13:22
נושא ההודעה:

ניסית ב gdb לכתוב

קוד:
set unwindonsignal off

?

במידה ואתה סוגר את האפשרות, האם זה עדיין מקריס?
 
   
תגובה  עם ציטוט חזרה למעלה
חזרה לתוכן הדיון
elcucoלא בפורום כעת ת.הצטרפות: 14/10/2003 · הודעות: 6258 ·
 

הודעה פורסם: 04/05/2023 - 14:55
נושא ההודעה:

Anonymous :
ניסית ב gdb לכתוב

קוד:
set unwindonsignal off

?

במידה ואתה סוגר את האפשרות, האם זה עדיין מקריס?


לא טרחתי. אבל אני חושב שאם אני צריך לעשות משהו בסביבת פיתוח שלי, כדי לקדם את התוכנה - אז זה לא פתרון טוב.

כמו שתכתבי - במקום לשהתמש ב־SIGEV_SIGNAL עברתי להשתמש ב־SIGEV_THREAD וקיבלתי את התוצאה הרצויה. תודה.
 
 צפיה בפרופיל המשתמש שלח הודעה פרטית  
תגובה  עם ציטוט חזרה למעלה
חזרה לתוכן הדיון
הצגת הודעות מלפני:     
מעבר אל:  
כל הזמנים הם GMT + 2 שעות
תגובה לנושא
צפיה בנושא הבא Printable version התחבר כדי לבדוק הודעות פרטיות צפיה בנושא הקודם
PNphpBB2 © 2003-2004 

תוכן הדיון

  1. elcuco
  2. elcuco
  3. elcuco
  4. אורח
  5. אורח
  6. אורח
  7. אורח
  8. elcuco