Commit Graph

221 Commits

Author SHA1 Message Date
Igor Kushnir
2655613543 ConcurrentQueue: simplify the constructor implementation
* threadCount argument: int => std::size_t to avoid implicit casting;
* eliminate temporary empty std::thread objects;
* replace a trivial lambda with a function pointer and its argument;
* get rid of the unused dedicated loop counter.
2021-12-29 09:36:44 +01:00
Igor Kushnir
d026050d49 ConcurrentQueue::jobsLeft: int => std::size_t
This data member's type can be unsigned because its value is never
negative now. Matching std::queue::size_type allows to improve type
safety, get rid of a static_cast and remove two assertions. The only
downside is a slight increase of sizeof(ConcurrentQueue).
2021-12-29 09:36:44 +01:00
Igor Kushnir
d8a6b7f432 ConcurrentQueue: std::move jobs
Moving a std::function can be faster than copying it. Correcting these
normally minor inefficiencies is important here because they occur under
a mutex lock.
2021-12-29 09:36:44 +01:00
Igor Kushnir
d869e1230b ConcurrentQueue::enqueue: increment jobsLeft before adding a job
ConcurrentQueueTest::randomCalls() built in Debug mode often crashes
when concurrent_queue_test.cpp is modified and ConcurrentQueueTest is
launched from Qt Creator so that the test is built and immediately run.
The crash is an assertion failure that occurs most of the time under
the described circumstances at different test data rows:
void YACReader::ConcurrentQueue::finalizeJobs(int): Assertion `jobsLeft >= count' failed.

The assertion fails because ConcurrentQueue::enqueue() adds a job into
the queue first and then increments jobsLeft. If the job is immediately
picked up and executed very fast, ConcurrentQueue::nextJob() can try to
finalize it before enqueue() increments jobsLeft.

Simply reordering the modifications of jobsLeft and _queue in enqueue()
ensures that jobsLeft is always non-negative and eliminates the
assertion failures. Note that ConcurrentQueue::finalizeJobs() is the
only other function that modifies (decreases) jobsLeft. finalizeJobs()
is always called *after* the queue's size is reduced. So the following
invariant is now maintained at all times and documented:
jobsLeft >= _queue.size().
2021-12-29 09:36:44 +01:00
Igor Kushnir
57eb8d0171 ConcurrentQueue::cancelPending: notify _waitVar
This allows to call cancelPending() and waitAll() concurrently with no
additional synchronization. While calling these two functions
concurrently may not be useful often, supporting it costs little in
terms of performance and code complexity. Furthermore, a completely
thread-safe class is easier to document and use correctly.

Optimize job finalization by notifying _waitVar only if jobsLeft is
reduced to 0.

Optimize cancelPending() by not locking jobsLeftMutex when no job is
canceled (if the queue is empty when this function is called).

Add assertions that verify invariants.

The output of ConcurrentQueueTest::randomCalls() reflects the fact that
a caller of waitAll() can be blocked indefinitely when another thread
cancels all queued jobs while no job is being executed. The test output
snippet below omits repetitive information: the
"QINFO  : ConcurrentQueueTest::randomCalls(queue{1}; 2 user thread(s))"
prefix of each line, current thread id and the common hh:mm:ss current
time part (leaving only the millisecond part). Note that thread #1
begins waiting at the 1st line of the snippet. "=> -8" means that total
equals -8 and thus ConcurrentQueue::jobsLeft equals 8. Thread #0 then
cancels all 8 queued jobs, then enqueues and cancels 3 jobs twice, then
momentarily waits 3 times. #1 is not waked until #0 enqueues 8 more jobs
and starts waiting for them too. Once these new 8 jobs are completed,
both #0 and #1 end waiting.

 1. [ms] 311 | #1 begin waiting for 1 thread => -8
 2. [ms] 311 | #0 enqueuing complete.
 3. [ms] 311 | #0 canceled 8 jobs => -8
 4. [ms] 311 | #0 enqueuing 3 jobs...
 5. [ms] 312 | #0 enqueuing complete.
 6. [ms] 312 | #0 canceled 3 jobs => -3
 7. [ms] 312 | #0 enqueuing 3 jobs...
 8. [ms] 312 | #0 enqueuing complete.
 9. [ms] 312 | #0 canceled 3 jobs => -3
10. [ms] 312 | #0 begin waiting for 1 thread => 0
11. [ms] 312 | #0 end waiting for 1 thread => 0
12. [ms] 312 | #0 begin waiting for 1 thread => 0
13. [ms] 312 | #0 end waiting for 1 thread => 0
14. [ms] 312 | #0 begin waiting for 1 thread => 0
15. [ms] 312 | #0 end waiting for 1 thread => 0
16. [ms] 312 | #0 canceled 0 jobs => 0
17. [ms] 312 | #0 canceled 0 jobs => 0
18. [ms] 312 | #0 enqueuing 3 jobs...
19. [ms] 312 | #0 enqueuing complete.
20. [ms] 312 | #0 enqueuing 3 jobs...
21. [ms] 312 | #0 enqueuing complete.
22. [ms] 312 | #0 enqueuing 2 jobs...
23. [ms] 312 | #0 enqueuing complete.
24. [ms] 312 | #0 begin waiting for 1 thread => -8
25. [ms] 312 | [0.1] sleep 0.003 ms...
26. [ms] 312 | [0.1] +1 => -7
27. [ms] 312 | [0.2] sleep 0.003 ms...
28. [ms] 312 | [0.2] +1 => -6
29. [ms] 312 | [0.3] sleep 0.003 ms...
30. [ms] 312 | [0.3] +1 => -5
31. [ms] 312 | [0.1] sleep 0 ms...
32. [ms] 313 | [0.1] +1 => -4
33. [ms] 313 | [0.2] sleep 0.005 ms...
34. [ms] 313 | [0.2] +1 => -3
35. [ms] 313 | [0.3] sleep 0 ms...
36. [ms] 313 | [0.3] +1 => -2
37. [ms] 313 | [0.1] sleep 0.001 ms...
38. [ms] 313 | [0.1] +1 => -1
39. [ms] 313 | [0.2] sleep 0.001 ms...
40. [ms] 313 | [0.2] +1 => 0
41. [ms] 313 | #0 end waiting for 1 thread => 0
42. [ms] 313 | #1 end waiting for 1 thread => 0
2021-12-29 09:36:44 +01:00
Igor Kushnir
e8b5f42e75 ConcurrentQueue::nextJob: notify all _waitVar threads
Replace _waitVar.notify_one() with _waitVar.notify_all(). This was the
only hurdle to documenting ConcurrentQueue::waitAll() as thread-safe.

ConcurrentQueueTest::waitAllFromMultipleThreads() passes instead of
hanging now.
2021-12-29 09:36:44 +01:00
Igor Kushnir
b43e3383d5 ConcurrentQueue::cancelPending: return the number of canceled jobs
The return value can be used to make
ConcurrentQueueTest::cancelPending1UserThread() non-flaky. It may also
be useful to non-testing code.

Improve the performance of cancelPending() by locking the two mutexes
separately and minimizing the locking time.
2021-12-29 09:36:44 +01:00
Igor Kushnir
a72fdb9ca2 ConcurrentQueue::cancelPending: don't reset jobsLeft to 0
Worker threads may well be executing jobs while this function is being
called. If ConcurrentQueue::waitAll() is called soon enough after
cancelPending(), the worker threads may still be running, but waitAll()
would return immediately as jobsLeft would be nonpositive.

Subtracting _queue.size() from jobsLeft sets this variable to the number
of worker threads that are executing jobs at the moment.

ConcurrentQueueTest::cancelPending1UserThread() passes most of the time
now. But it still fails occasionally because it depends on the timing of
thread scheduling, which is unreliable.
2021-12-29 09:36:44 +01:00
Igor Kushnir
228fe1284e Fix a typo in ConcurrentQueue::cancelPending function name 2021-12-29 09:36:44 +01:00
Luis Ángel San Martín
e7f3d29477 Tag ComicDB::operator== as const 2021-10-19 00:00:08 +02:00
Luis Ángel San Martín
5fbd100449 Use non deprecated QStandardPaths and remove Qt4 alternative 2021-10-19 00:00:08 +02:00
Luis Ángel San Martín
dc8c6e23e9 Use angleDelta instead of delta 2021-10-19 00:00:08 +02:00
Luis Ángel San Martín
d47bd55fa0 Don't use helper function to avoid raising the Qt5 min version requeriment 2021-10-19 00:00:08 +02:00
Luis Ángel San Martín
f300bc3aa0 Include QMetaType explicitly 2021-10-19 00:00:08 +02:00
Luis Ángel San Martín
b83d7150d7 Use QElapsedTimer instead of QTime 2021-10-19 00:00:08 +02:00
Luis Ángel San Martín
bdb23de74a Use fully qualified names 2021-10-19 00:00:08 +02:00
Luis Ángel San Martín
9ebd6e32da Fix QtOpenGL* includes in Qt6 2021-10-19 00:00:08 +02:00
Luis Ángel San Martín
35fa03549b Use fully qualified names 2021-10-19 00:00:08 +02:00
Luis Ángel San Martín
326cebdf7f *Ref methods are deprecated in Qt6 2021-10-19 00:00:08 +02:00
Luis Ángel San Martín
a792a03760 Use QRegularExpression instead of QRegExp 2021-10-19 00:00:08 +02:00
Luis Ángel San Martín
ecd1497370 Don't use virtual methods unnecessarily 2021-10-19 00:00:08 +02:00
Luis Ángel San Martín
db433be88c Include QRegExp explicitly 2021-10-19 00:00:08 +02:00
Luis Ángel San Martín
b878e8169e Replace QDateTime constructor
Using the last moment of the day is enough because all other dates in bookmarks have happened before.
2021-10-19 00:00:08 +02:00
Luis Ángel San Martín
459883d7be Use *Ref methods instead 2021-10-19 00:00:07 +02:00
Luis Ángel San Martín
a56914bec3 Do not use foreach 2021-10-19 00:00:07 +02:00
Luis Ángel San Martín
c1d3fb0778 Proper use of range for 2021-10-19 00:00:07 +02:00
Luis Ángel San Martín
c03b1075f3 Do not mix const an non-const iterators 2021-10-19 00:00:07 +02:00
Luis Ángel San Martín
5557cfe5b3 Remove unused variable 2021-10-19 00:00:07 +02:00
Luis Ángel San Martín
e1ed292a91 Convert emit(signal()) calls to emit signal() 2021-10-19 00:00:07 +02:00
Luis Ángel San Martín
5aa02a19bb clang-format 2021-10-18 21:56:52 +02:00
Luis Ángel San Martín
a77facce6d Add helper properties for parsing day/month/year sequentially 2021-09-27 15:28:05 +02:00
Luis Ángel San Martín
b0a6411528 Initialize attributes in constructor 2021-09-27 15:27:44 +02:00
Felix Kauselmann
76ab23b776 Common: Convert last signals to new slot syntax 2021-06-29 13:53:12 +02:00
Felix Kauselmann
47324e7f22 Comic/Render: Use overloads refactor some SIGNAL/SLOT connections to new syntax 2021-06-29 13:53:12 +02:00
Felix Kauselmann
ae8e47d863 Clazy: Add second batch of SIGNAL/SLOT removal 2021-06-29 13:53:12 +02:00
Felix Kauselmann
f813a018d2 Comic: Virtual prototype for process(), fix signal/slot 2021-06-29 13:53:12 +02:00
Luis Ángel San Martín
891546b423 9.8.2 release 2021-06-19 18:13:01 +02:00
Luis Ángel San Martín
1c382aef72 Update version to 9.8.1 2021-06-02 18:57:41 +02:00
Luis Ángel San Martín
51284cb652 Add new struct to represent the source where a comic can be opened from
A comic always belongs to a Folder, but when we open one its siblings may be different in we are opening it from a Reading List. I am not sure that Tags should keep the reading order because their purpose is abstract, so their behaviour will be opening the comics from theirs container folders.
2021-05-27 18:35:08 +02:00
Luis Ángel San Martín
b8ad99fcaa Exract struct to reuse it 2021-04-30 09:52:31 +02:00
Igor Kushnir
21c3bda5d4 YACReaderFlowGL: initialize data member texture pointers
Moving the initialization of defaultTexture out of the member
initializer list gets rid of a GCC's -Wreorder warning.

Initialize other texture pointers to improve safety and consistency.
2021-03-09 21:32:23 +01:00
Felix Kauselmann
81b4d25b5c Remove unneeded QtOpenGL dependency
Qt OpenGL in Qt5 is a deprecated module that is discouraged for
new code usage. We have been including this module in our builds
despite not relying on its functionality for a long time now -
probably an oversight from porting to the newer functions.

Time to remove it.

IMPORTANT INFORMATION: In Qt6, a lot of functionality that was
provided by Qt GUI was moved into the 'new' Qt6 Qt OpenGL module.
Thus, even if it makes perfectly sense to remove it for Qt5 builds
we will likely have to restore it for Qt6 builds at a later time.
2021-03-09 18:26:01 +01:00
Luis Ángel San Martín
93596a4972 Restore needed lock 2021-02-08 09:02:19 +01:00
Luis Ángel San Martín
4c93c70de6 Use the right mutex when the queue is modified 2021-02-08 08:32:42 +01:00
Luis Ángel San Martín
60de69635b Get/set new manga field from/to the db 2021-01-16 18:30:25 +01:00
Luis Ángel San Martín
3ab05c6777 Add a new boolean field for tagging comics as manga 2021-01-16 14:23:59 +01:00
Luis Ángel San Martín
c3b0780e03 Remove unused constant 2021-01-14 11:37:37 +01:00
Luis Ángel San Martín
fa5ce25425 Add concurrent queue based on lambdas 2021-01-14 09:03:17 +01:00
smahot
f6bed8590f Support for third party qt image plugins 2020-09-30 19:01:12 +02:00
Luis Ángel San Martín
948ed595e7 Bump version number to 9.7.1 2020-09-12 12:02:55 +02:00
Luis Ángel San Martín
c490b70b68 Move declaration to the viewer group 2020-09-07 18:13:06 +02:00
Luis Ángel San Martín
bb09be3d6a Bump version number 2020-09-03 18:05:05 +02:00
Luis Ángel San Martín
802e0d32ce Fix trying to scale images on null images 2020-09-03 18:00:29 +02:00
Felix Kauselmann
5bb6ab276a Reader: Add option to show covers as single pages in double page mode 2020-09-03 15:32:45 +02:00
Felix Kauselmann
232181eef7 Reader: Add option to stop enlarging images in fit to width and height 2020-09-02 09:27:53 +02:00
Luis Ángel San Martín
5f0889f332 Format 2020-08-31 16:19:42 +02:00
Luis Ángel San Martín
a2b4b88801 Format 2020-08-31 16:04:26 +02:00
Igor Kushnir
cb7c967252 Add WorkerThread class and use it in ComicFlow
In a later commit WorkerThread should also replace classes similar to
ImageLoader: PageLoader, ImageLoaderGL and ImageLoaderByteArrayGL.

Bugs fixed:
  1. Eliminated a data race between ImageLoader::run() and
ComicFlow::updateImageData()->ImageLoader::result(). Specifically when
ImageLoader::busy() returns false, then ImageLoader::run() sets
ImageLoader::working to true, loads the image and starts assigning it to
ImageLoader::img, while ImageLoader::result() is accessed without
locking from updateImageData().
Making ImageLoader::working atomic is clearly insufficient to eliminate
this data race. The fix is to set 'working' to true immediately and
synchronously as soon as a new task is assigned to the worker.
  2. Replaced thread termination with graceful thread exit. ComicFlow
destructor called QThread::terminate(), using which is discouraged by Qt
documentation. The application exited without errors in Release mode.
In Debug mode, however, it received the SIG32 signal on exit and printed
the following warning - "QWaitCondition: mutex destroy failure:
Device or resource busy".
The loop in WorkerThread::run() is no longer endless. The worker thread
properly ends and is joined in WorkerThread destructor.

Design decisions:
 1. WorkerThread could emit a signal when it completes a task.
Thus updateTimer could be removed from ComicFlow and GoToFlow. However,
there is no obvious way to use this new signal in the two GL classes.
Also I don't know whether updateTimer is just an inefficient polling
substitute for notification or an intentional animation mechanism.
 2. The index variable is no longer stored in the worker class, but in
ComicFlow directly. Thing is, this data member was never actually
accessed by the worker, but ComicFlow went so far as to lock worker's
mutex to "protect" access to the index.
 3. The common ImageLoader implementation turned out to be very general.
So I converted it into the WorkerThread class template that is not
restricted to producing QImage results and can be reused elsewhere.
 4. I used standard classes (such as std::thread) instead of their Qt
equivalents (e.g. QThread) because they are more thoroughly documented.
The standard classes should also be more efficient as they were more
carefully designed and provide much fewer unnecessary features.
 5. Release-Acquire ordering is safe for the WorkerThread::working
use case and is more efficient than the std::atomic-default
Sequentially-consistent ordering.
 6. condition.notify_one() is called while the mutex is unlocked
to improve performance. This is safe in both cases:
  a) if the worker thread exits due to a spurious wakeup just before
the condition.notify_one() call in WorkerThread destructor, so much the
better;
  b) if a spurious wakeup lets the worker thread finish the task and
start waiting on the condition again just before the
condition.notify_one() call in WorkerThread::performTask(), the second
waking will be ignored by the worker thread as 'working' and 'abort'
will be false then.
2020-08-31 15:45:12 +02:00
Felix Kauselmann
b9acd13120
Fix code format errors due to changes in default coding style. (#150) 2020-07-24 21:17:49 +02:00
Luis Ángel San Martín
092611f0cd Send read status for imported comics 2020-05-09 22:19:00 +02:00
Jeremy Douglass
15c126fda5
Enable unarr 7z support. Closes #113 (#115)
* Enable unarr 7z support. Closes #113
2020-02-12 08:38:03 +01:00
Luis Ángel San Martín
f65395c11d Bump version number 2019-09-28 10:15:17 +02:00
Luis Ángel San Martín
d49c8895ff Bump version number 2019-09-27 18:33:08 +02:00
Luis Ángel San Martín
0b83764734
Revert "Thread ping pong" 2019-09-24 12:00:21 +02:00
Luis Ángel San Martín
7ed19ddd78 Fix scope
GitKraken has some serious issues when resolving conflicts
2019-09-24 09:17:39 +02:00
Felix Kauselmann
cc71f419cc Revert "Backout changeset c42e71e42d7968ddb6c63fd39011669503b9122c"
This reverts commit 040664d3ba.
2019-09-24 08:12:38 +02:00
Luis Ángel San Martín
8603b8ca14 Get the latest version number from the code in master 2019-09-22 12:27:51 +02:00
Luis Ángel San Martín
3923da2344 Add new define to remember if we have notified the user about close to tray 2019-09-21 10:42:38 +02:00
Luis Ángel San Martín
80cd4f64f8 Rename setting
We are going to use close to system tray instead of minimize, easier to handle it at a crossplatform level
2019-09-21 10:42:15 +02:00
Felix Kauselmann
e587f59ddb Add support for minimize and start to tray. 2019-09-19 20:22:14 +02:00
Igor Kushnir
82719573b5 Reader: store geometry instead of pos&size in Configuration
Qt documentation recommends calling saveGeometry() in closeEvent().

This commit fixes the following bug on my GNU/Linux with Xfce system:
    1. Move the top of the YACReader window to the top of the screen.
    2. Restart YACReader (exit and run again).
    2. Enter full screen mode.
    4. Restart YACReader.
    5. Exit full screen mode.
At this point YACReader's title bar is hidden beyond the top of the
screen, i.e. the window has moved up.
2019-09-18 18:10:40 +02:00
Luis Ángel San Martín
2649f58f15 Include lastTimeOpened in plain text comic info 2019-09-10 17:16:53 +02:00
Felix Kauselmann
fb2684292b Fix code formatting. 2019-08-24 14:37:25 +02:00
Felix Kauselmann
bcba08d344 OpenGL CoverFlow: Restore antialiasing
We previously had to disable antialiasing because z-buffer
picking did not work with multisampling enabled. Now we
have raytracing, so we can restore it.
2019-08-24 14:37:25 +02:00
Felix Kauselmann
622978b2bd OpenGL coverflow: Replace z-buffer picking with raytracing. 2019-08-24 14:37:25 +02:00
Luis Ángel San Martín
54fcb059b1 Bump version number 2019-08-24 11:11:51 +02:00
Luis Ángel San Martín
4f4c562a33 Add setting to disable the continue reading banner in the grid view 2019-08-11 11:47:14 +02:00
Luis Ángel San Martín
98a6ef5698 Initialize pointer and use less restrictive condition in destructor 2019-06-02 09:37:40 +02:00
Luis Ángel San Martín
5db5fb7e0c Fix crash when closing YACReader with an empty go to flow gl 2019-06-02 09:28:54 +02:00
Luis Ángel San Martín
c06e8c0fc6 Fix YACReaderPageFlowGL texture destruction 2019-06-01 16:13:29 +02:00
Luis Ángel San Martín
e3ec56aa43 Format code using clang-format 2019-05-30 19:46:37 +02:00
Luis Ángel San Martín
ca34e99ec4
Merge pull request #57 from vedgy/misc-code-fixes
Miscellaneous code fixes
2019-05-30 18:24:53 +02:00
Igor Kushnir
92cf54980c Library: eliminate QPainter warnings
There were many run-time warnings in YACReaderLibrary built in Debug
mode with hardware acceleration disabled and with ClassicComicsView
as the active comics view:
    QWidget::paintEngine: Should no longer be called
    QPainter::begin: Paint device returned engine == 0, type: 1

The ComicFlowWidgetSW::paintEvent() implementation now corresponds to
ComicFlowWidgetGL::paintEvent(), which has been fixed earlier.

QWidget::repaint() calls paintEvent() immediately.
PictureFlow::paintEvent() calls d->renderer->paint(). So the
d->renderer->paint() call in PictureFlow::updateMarks() was redundant.
2019-05-22 17:37:04 +03:00
Felix Kauselmann
caca3191f9 Flow: Remove glu dependency 2019-05-06 07:38:33 +02:00
Felix Kauselmann
d9d93c6481 gl flow: clean up includes 2019-05-05 11:17:45 +02:00
Felix Kauselmann
7bd04ca7d5 remove legacy flow implementation
We no longer support builds using the legacy flow.
2019-05-05 09:39:07 +02:00
Luis Ángel San Martín
14f1609ffa
Merge pull request #43 from mytskine/fix-gcc8-warnings-develop
Fix gcc8 warnings
2019-04-19 16:56:56 +02:00
François Gannaz
88f668d663 bugfix: 'switch case' for OpenVG had no 'break' 2019-04-03 20:44:57 +00:00
François Gannaz
b2f44a939e fix misleading indentation of YACReaderFlowGL::remove 2019-04-01 11:25:16 +02:00
François Gannaz
f87e113f89 fix misleading indentation of YACReaderFlowGL::setCurrentIndex 2019-04-01 11:25:16 +02:00
François Gannaz
472e9f9832 reorder initialization of YACReaderFlowGL 2019-04-01 11:25:16 +02:00
François Gannaz
9ace47ccc0 explicit parenthesis in complex comparison 2019-04-01 11:23:33 +02:00
François Gannaz
8879e7abc5 Initialize parent class 2019-04-01 11:23:33 +02:00
François Gannaz
4f7f760960 fix misleading indentation of ComicDB::toTXT 2019-04-01 11:23:33 +02:00
François Gannaz
7b9502bd97 fix misleading indentation of PictureFlow::showSlide 2019-04-01 11:23:33 +02:00
François Gannaz
fae244b4e3 typecast comparison in PictureFlow::showSlide 2019-04-01 11:23:33 +02:00
François Gannaz
e084bdd447 cases missing in 'switch' in PictureFlow 2019-04-01 11:23:33 +02:00
François Gannaz
0c02564fc5 cases missing in 'switch' in PictureFlow 2019-04-01 11:23:33 +02:00
François Gannaz
f012a6d30e reorder initialization of PictureFlowState 2019-04-01 11:23:33 +02:00
François Gannaz
0e0d707faf reorder initialization of Comic::Comic 2019-04-01 09:08:45 +02:00