EPERM возвращается, если поток, который вызывает timedwait, не имеет мьютекса. Вы должны заблокировать мьютекс перед вызовом timedwait. Кроме того, переместите статическую инициализацию мьютекса и конвара в область файлов.
UPDATE: если вы инициализируете мьютекс как муфту для проверки ошибок, Linux также завершится с EPERM (так как UB вызывает вызов pthread_cond_wait / timedwait без сохранения мьютекса).
Измененный код ниже:
//#define _BSD_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#include <sys/time.h>
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex;
void *thread_handler(void *ptr){
struct timespec ts;
struct timeval tp;
gettimeofday(&tp, NULL);
ts.tv_sec = tp.tv_sec;
ts.tv_nsec = tp.tv_usec*1000;
ts.tv_sec += 2;
//Invoke pthread_cond_timedwait() to wait for 2 seconds
int rcode = pthread_cond_timedwait(&cond, &mutex, &ts);
if (rcode == ETIMEDOUT)
printf("Terminated due to time out\n");
else if (rcode == EPERM)
printf("Terminated due to EPERM\n");
else
printf("Return code is %d\n", rcode);
return NULL;
}
int main(int argc, char** argv){
pthread_mutexattr_t mta;
pthread_mutexattr_init(&mta);
pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_ERRORCHECK);
pthread_mutex_init(&mutex, &mta);
pthread_t thread;
// start the thread
pthread_create(&thread, NULL, &thread_handler, NULL);
// wait for thread to finish
pthread_join(thread, NULL);
return 0;
}
Протестировано на ядре SMP Debian 4.9.82-1 + deb9u3 (2018-03-02) x86_64 GNU / Linux, дистрибутив Debian GNU / Linux buster / sid.
Если вы используете Firebird 3, вы можете использовать оконные функции :
select count(*) over(), column1, column2, etc
from sometable
where somecondition
order by something
fetch first 10 rows only
При этом используется пункт fetch
, введенный в Firebird 3. [ 119]
В более ранних версиях сделать это немного сложнее, но, например, в Firebird 2.1 и выше, вы можете использовать общее табличное выражение, чтобы избежать необходимости повторять запрос и условия:
with actualquery as (
select column1, column2, etc
from sometable
where somecondition
)
select (select count(*) from actualquery), column1, column2, etc
from actualquery
order by something
rows 10
Используется пункт rows
(который аналогичен select first 10
)
Вам нужно два отдельных запроса.
Один из них заключается в получении ограниченного набора строк с использованием SQL-совместимого offset
fetch
начиная с Firebird 3 или альтернативно rows
или first
& amp; skip
:
select field1, field2
from mytable
[where conditions]
[offset 0 rows] fetch first 10 rows only
Еще один способ - получить общее количество записей:
select count(*) from mytable [where conditions]
Обратите внимание, что последний запрос может быть дорогостоящим для сложных запросов и / или большое количество данных. Обычно на большом количестве данных используются другие подходы. Один из них посвящен двигателям FTS, таким как SphinxSearch. Google, например, даст вам приблизительное количество результатов.