Skip to content

Commit

Permalink
Merge pull request #293 from genicam/some-more-updates-on-fix-for-iss…
Browse files Browse the repository at this point in the history
…ue-289

Some more updates on fix for issue 289
  • Loading branch information
kazunarikudo authored Mar 1, 2022
2 parents 03f4149 + 8f17098 commit bfd47ca
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 15 deletions.
63 changes: 48 additions & 15 deletions src/harvesters/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -1407,7 +1407,8 @@ def __init__(
_logger.debug('created: {0}'.format(self._sigint_handler))

self._num_images_to_acquire = 0
self._timeout_for_image_acquisition = 1 # ms
self._timeout_on_internal_fetch_call = 1 # ms
self._timeout_on_client_fetch_call = 0.01 # s
self._statistics = Statistics()
self._announced_buffers = []

Expand Down Expand Up @@ -1721,19 +1722,49 @@ def is_armed(self) -> bool:
return True

@property
def timeout_for_image_acquisition(self) -> int:
def timeout_on_client_fetch_call(self) -> float:
"""
It is used to define the timeout duration on a single fetch
method calL. The unit is [s].
:getter:
:setter:
:type: float
"""
return self._timeout_on_client_fetch_call

@timeout_on_client_fetch_call.setter
def timeout_on_client_fetch_call(self, value: float):
if value <= self.timeout_on_internal_fetch_call:
raise ValueError("it must be > timeout_on_internal_fetch_call")
self._timeout_on_client_fetch_call = value

@property
def timeout_on_internal_fetch_call(self) -> int:
"""
The unit is [ms].
It is used to define the timeout duration on an internal single GenTL
fetch calL. The unit is [ms].
:getter:
:setter:
:type: int
"""
return self._timeout_for_image_acquisition
return self._timeout_on_internal_fetch_call

@timeout_on_internal_fetch_call.setter
def timeout_on_internal_fetch_call(self, value):
self._timeout_on_internal_fetch_call = value

@property
def timeout_for_image_acquisition(self) -> int:
"""
Deprecated: Use timeout_on_internal_fetch_call instead.
"""
return self._timeout_on_internal_fetch_call

@timeout_for_image_acquisition.setter
def timeout_for_image_acquisition(self, ms):
self._timeout_for_image_acquisition = ms
self._timeout_on_internal_fetch_call = ms

@property
def thread_image_acquisition(self) -> ThreadBase:
Expand Down Expand Up @@ -2019,7 +2050,7 @@ def worker_image_acquisition(self) -> None:

for manager in self._event_new_buffer_managers:
buffer = self._fetch(manager=manager,
timeout=self._timeout_for_image_acquisition*2/1000)
timeout_on_client_fetch_call=self.timeout_on_client_fetch_call)
if buffer:
if self.buffer_handling_mode == 'OldestFirstOverwrite':
with MutexLocker(self.thread_image_acquisition):
Expand Down Expand Up @@ -2095,37 +2126,39 @@ def try_fetch(self, *, timeout: float = 0,
:rtype: Optional[Buffer]
"""
buffer = self._fetch(manager=self._event_new_buffer_managers[0],
timeout=timeout, throw_except=False)
timeout_on_client_fetch_call=timeout,
throw_except=False)

if buffer:
buffer = self._finalize_fetching_process(buffer, is_raw)
self._emit_callbacks(self.Events.NEW_BUFFER_AVAILABLE)
return buffer

def _fetch(self, *, manager: EventManagerNewBuffer, timeout: float = 0,
def _fetch(self, *, manager: EventManagerNewBuffer,
timeout_on_client_fetch_call: float = 0,
throw_except: bool = False) -> Optional[Buffer_]:
global _logger

assert manager

buffer = None
watch_timeout = True if timeout > 0 else False
watch_timeout = True if timeout_on_client_fetch_call > 0 else False
base = time.time()

while not buffer:
if watch_timeout:
elapsed = time.time() - base
if elapsed > timeout:
if elapsed > timeout_on_client_fetch_call:
_logger.debug(
'timeout: elapsed {0} sec.'.format(timeout))
'timeout: elapsed {0} sec.'.format(
timeout_on_client_fetch_call))
if throw_except:
raise TimeoutException
else:
return None

try:
manager.update_event_data(
self._timeout_for_image_acquisition)
manager.update_event_data(self.timeout_on_internal_fetch_call)
except TimeoutException:
continue
else:
Expand Down Expand Up @@ -2202,8 +2235,8 @@ def fetch_buffer(self, *, timeout: float = 0, is_raw: bool = False,
time.sleep(cycle_s if cycle_s else 0.0001)
else:
buffer = self._fetch(
manager=self._event_new_buffer_managers[0], timeout=timeout,
throw_except=True)
manager=self._event_new_buffer_managers[0],
timeout_on_client_fetch_call=timeout, throw_except=True)
if buffer:
buffer = self._finalize_fetching_process(buffer, is_raw)
self._emit_callbacks(self.Events.NEW_BUFFER_AVAILABLE)
Expand Down
10 changes: 10 additions & 0 deletions src/harvesters/test/test_harvester_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ def test_timeout_on_fetching_buffer(self):

timeout = 3 # sec

self._logger.info("you will see timeout but that's intentional.")
with self.assertRaises(TimeoutException):
# Try to fetch a buffer but the IA will immediately raise
# TimeoutException because it's not started image acquisition:
Expand All @@ -259,6 +260,7 @@ def test_timeout_on_fetching_buffer(self):
# We're ready to start image acquisition:
ia.start_acquisition()

self._logger.info("you will see timeout but that's intentional.")
with self.assertRaises(TimeoutException):
# Try to fetch a buffer but the IA will raise TimeoutException
# because we've not triggered the device so far:
Expand Down Expand Up @@ -299,6 +301,7 @@ def test_try_fetch_with_timeout(self):

# Try to fetch a buffer but None will be returned
# because we've not triggered the device so far:
self._logger.info("you will see timeout but that's intentional.")
buffer = ia.try_fetch(timeout=timeout)
self.assertIsNone(buffer)

Expand Down Expand Up @@ -353,6 +356,8 @@ def test_num_holding_filled_buffers(self):
self.ia.num_filled_buffers_to_hold = num_images

# Start image acquisition:
self._logger.info(
"you will see timeout but that's intentional.")
self.ia.start_acquisition(run_in_background=True)

# Run a test:
Expand All @@ -371,6 +376,7 @@ def _test_issue_120_1(self, num_images):

# Trigger it:
self.generate_software_trigger(sleep_s=self.sleep_duration)
self._logger.info("triggered.")

# It must be incremented:
self.assertEqual(
Expand All @@ -380,6 +386,7 @@ def _test_issue_120_1(self, num_images):
# Trigger it again, we know it's redundant compared to the
# maximum capacity:
self.generate_software_trigger(sleep_s=self.sleep_duration)
self._logger.info("triggered.")

# Make sure num_holding_filled_buffers does not exceed
# num_filled_buffers_to_hold:
Expand Down Expand Up @@ -576,6 +583,7 @@ def test_issue_141(self):
self.assertEqual(0, len(self.on_new_buffer_available.buffers))

# Run a sub-test:
self._logger.info("you will see timeout but that's intentional.")
test()

# Then stop image acquisition:
Expand Down Expand Up @@ -616,11 +624,13 @@ def _test_141_without_callback(self):

def _test_141_body(self):
# Start image acquisition:
self._logger.info("going to start acquisition in the background.")
self.ia.start_acquisition(run_in_background=True)

# Trigger the target device:
for _ in range(self.num_images):
self.generate_software_trigger(sleep_s=self.sleep_duration)
self._logger.info("triggered.")

def test_issue_150(self):
# Create an image acquirer:
Expand Down

0 comments on commit bfd47ca

Please sign in to comment.