📄 jmemmgr.c
字号:
(*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info,
(void FAR *) ptr->mem_buffer[i],
file_offset, byte_count);
file_offset += byte_count;
}
}
METHODDEF(JSAMPARRAY)
access_virt_sarray (j_common_ptr cinfo, jvirt_sarray_ptr ptr,
JDIMENSION start_row, JDIMENSION num_rows,
boolean writable)
/* Access the part of a virtual sample array starting at start_row */
/* and extending for num_rows rows. writable is true if */
/* caller intends to modify the accessed area. */
{
JDIMENSION end_row = start_row + num_rows;
JDIMENSION undef_row;
/* debugging check */
if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess ||
ptr->mem_buffer == NULL)
ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
/* Make the desired part of the virtual array accessible */
if (start_row < ptr->cur_start_row ||
end_row > ptr->cur_start_row+ptr->rows_in_mem) {
if (! ptr->b_s_open)
ERREXIT(cinfo, JERR_VIRTUAL_BUG);
/* Flush old buffer contents if necessary */
if (ptr->dirty) {
do_sarray_io(cinfo, ptr, TRUE);
ptr->dirty = FALSE;
}
/* Decide what part of virtual array to access.
* Algorithm: if target address > current window, assume forward scan,
* load starting at target address. If target address < current window,
* assume backward scan, load so that target area is top of window.
* Note that when switching from forward write to forward read, will have
* start_row = 0, so the limiting case applies and we load from 0 anyway.
*/
if (start_row > ptr->cur_start_row) {
ptr->cur_start_row = start_row;
} else {
/* use long arithmetic here to avoid overflow & unsigned problems */
long ltemp;
ltemp = (long) end_row - (long) ptr->rows_in_mem;
if (ltemp < 0)
ltemp = 0; /* don't fall off front end of file */
ptr->cur_start_row = (JDIMENSION) ltemp;
}
/* Read in the selected part of the array.
* During the initial write pass, we will do no actual read
* because the selected part is all undefined.
*/
do_sarray_io(cinfo, ptr, FALSE);
}
/* Ensure the accessed part of the array is defined; prezero if needed.
* To improve locality of access, we only prezero the part of the array
* that the caller is about to access, not the entire in-memory array.
*/
if (ptr->first_undef_row < end_row) {
if (ptr->first_undef_row < start_row) {
if (writable) /* writer skipped over a section of array */
ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
undef_row = start_row; /* but reader is allowed to read ahead */
} else {
undef_row = ptr->first_undef_row;
}
if (writable)
ptr->first_undef_row = end_row;
if (ptr->pre_zero) {
size_t bytesperrow = (size_t) ptr->samplesperrow * SIZEOF(JSAMPLE);
undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */
end_row -= ptr->cur_start_row;
while (undef_row < end_row) {
jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow);
undef_row++;
}
} else {
if (! writable) /* reader looking at undefined data */
ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
}
}
/* Flag the buffer dirty if caller will write in it */
if (writable)
ptr->dirty = TRUE;
/* Return address of proper part of the buffer */
return ptr->mem_buffer + (start_row - ptr->cur_start_row);
}
METHODDEF(JBLOCKARRAY)
access_virt_barray (j_common_ptr cinfo, jvirt_barray_ptr ptr,
JDIMENSION start_row, JDIMENSION num_rows,
boolean writable)
/* Access the part of a virtual block array starting at start_row */
/* and extending for num_rows rows. writable is true if */
/* caller intends to modify the accessed area. */
{
JDIMENSION end_row = start_row + num_rows;
JDIMENSION undef_row;
/* debugging check */
if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess ||
ptr->mem_buffer == NULL)
ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
/* Make the desired part of the virtual array accessible */
if (start_row < ptr->cur_start_row ||
end_row > ptr->cur_start_row+ptr->rows_in_mem) {
if (! ptr->b_s_open)
ERREXIT(cinfo, JERR_VIRTUAL_BUG);
/* Flush old buffer contents if necessary */
if (ptr->dirty) {
do_barray_io(cinfo, ptr, TRUE);
ptr->dirty = FALSE;
}
/* Decide what part of virtual array to access.
* Algorithm: if target address > current window, assume forward scan,
* load starting at target address. If target address < current window,
* assume backward scan, load so that target area is top of window.
* Note that when switching from forward write to forward read, will have
* start_row = 0, so the limiting case applies and we load from 0 anyway.
*/
if (start_row > ptr->cur_start_row) {
ptr->cur_start_row = start_row;
} else {
/* use long arithmetic here to avoid overflow & unsigned problems */
long ltemp;
ltemp = (long) end_row - (long) ptr->rows_in_mem;
if (ltemp < 0)
ltemp = 0; /* don't fall off front end of file */
ptr->cur_start_row = (JDIMENSION) ltemp;
}
/* Read in the selected part of the array.
* During the initial write pass, we will do no actual read
* because the selected part is all undefined.
*/
do_barray_io(cinfo, ptr, FALSE);
}
/* Ensure the accessed part of the array is defined; prezero if needed.
* To improve locality of access, we only prezero the part of the array
* that the caller is about to access, not the entire in-memory array.
*/
if (ptr->first_undef_row < end_row) {
if (ptr->first_undef_row < start_row) {
if (writable) /* writer skipped over a section of array */
ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
undef_row = start_row; /* but reader is allowed to read ahead */
} else {
undef_row = ptr->first_undef_row;
}
if (writable)
ptr->first_undef_row = end_row;
if (ptr->pre_zero) {
size_t bytesperrow = (size_t) ptr->blocksperrow * SIZEOF(JBLOCK);
undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */
end_row -= ptr->cur_start_row;
while (undef_row < end_row) {
jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow);
undef_row++;
}
} else {
if (! writable) /* reader looking at undefined data */
ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
}
}
/* Flag the buffer dirty if caller will write in it */
if (writable)
ptr->dirty = TRUE;
/* Return address of proper part of the buffer */
return ptr->mem_buffer + (start_row - ptr->cur_start_row);
}
/*
* Release all objects belonging to a specified pool.
*/
METHODDEF(void)
free_pool (j_common_ptr cinfo, int pool_id)
{
my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
small_pool_ptr shdr_ptr;
large_pool_ptr lhdr_ptr;
size_t space_freed;
if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS)
ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */
#ifdef MEM_STATS
if (cinfo->err->trace_level > 1)
print_mem_stats(cinfo, pool_id); /* print pool's memory usage statistics */
#endif
/* If freeing IMAGE pool, close any virtual arrays first */
if (pool_id == JPOOL_IMAGE) {
jvirt_sarray_ptr sptr;
jvirt_barray_ptr bptr;
for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) {
if (sptr->b_s_open) { /* there may be no backing store */
sptr->b_s_open = FALSE; /* prevent recursive close if error */
(*sptr->b_s_info.close_backing_store) (cinfo, & sptr->b_s_info);
}
}
mem->virt_sarray_list = NULL;
for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) {
if (bptr->b_s_open) { /* there may be no backing store */
bptr->b_s_open = FALSE; /* prevent recursive close if error */
(*bptr->b_s_info.close_backing_store) (cinfo, & bptr->b_s_info);
}
}
mem->virt_barray_list = NULL;
}
/* Release large objects */
lhdr_ptr = mem->large_list[pool_id];
mem->large_list[pool_id] = NULL;
while (lhdr_ptr != NULL) {
large_pool_ptr next_lhdr_ptr = lhdr_ptr->hdr.next;
space_freed = lhdr_ptr->hdr.bytes_used +
lhdr_ptr->hdr.bytes_left +
SIZEOF(large_pool_hdr);
jpeg_free_large(cinfo, (void FAR *) lhdr_ptr, space_freed);
mem->total_space_allocated -= space_freed;
lhdr_ptr = next_lhdr_ptr;
}
/* Release small objects */
shdr_ptr = mem->small_list[pool_id];
mem->small_list[pool_id] = NULL;
while (shdr_ptr != NULL) {
small_pool_ptr next_shdr_ptr = shdr_ptr->hdr.next;
space_freed = shdr_ptr->hdr.bytes_used +
shdr_ptr->hdr.bytes_left +
SIZEOF(small_pool_hdr);
jpeg_free_small(cinfo, (void *) shdr_ptr, space_freed);
mem->total_space_allocated -= space_freed;
shdr_ptr = next_shdr_ptr;
}
}
/*
* Close up shop entirely.
* Note that this cannot be called unless cinfo->mem is non-NULL.
*/
METHODDEF(void)
self_destruct (j_common_ptr cinfo)
{
int pool;
/* Close all backing store, release all memory.
* Releasing pools in reverse order might help avoid fragmentation
* with some (brain-damaged) malloc libraries.
*/
for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) {
free_pool(cinfo, pool);
}
/* Release the memory manager control block too. */
jpeg_free_small(cinfo, (void *) cinfo->mem, SIZEOF(my_memory_mgr));
cinfo->mem = NULL; /* ensures I will be called only once */
jpeg_mem_term(cinfo); /* system-dependent cleanup */
}
/*
* Memory manager initialization.
* When this is called, only the error manager pointer is valid in cinfo!
*/
GLOBAL(void)
jinit_memory_mgr (j_common_ptr cinfo)
{
my_mem_ptr mem;
long max_to_use;
int pool;
size_t test_mac;
cinfo->mem = NULL; /* for safety if init fails */
/* Check for configuration errors.
* SIZEOF(ALIGN_TYPE) should be a power of 2; otherwise, it probably
* doesn't reflect any real hardware alignment requirement.
* The test is a little tricky: for X>0, X and X-1 have no one-bits
* in common if and only if X is a power of 2, ie has only one one-bit.
* Some compilers may give an "unreachable code" warning here; ignore it.
*/
if ((SIZEOF(ALIGN_TYPE) & (SIZEOF(ALIGN_TYPE)-1)) != 0)
ERREXIT(cinfo, JERR_BAD_ALIGN_TYPE);
/* MAX_ALLOC_CHUNK must be representable as type size_t, and must be
* a multiple of SIZEOF(ALIGN_TYPE).
* Again, an "unreachable code" warning may be ignored here.
* But a "constant too large" warning means you need to fix MAX_ALLOC_CHUNK.
*/
test_mac = (size_t) MAX_ALLOC_CHUNK;
if ((long) test_mac != MAX_ALLOC_CHUNK ||
(MAX_ALLOC_CHUNK % SIZEOF(ALIGN_TYPE)) != 0)
ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK);
max_to_use = jpeg_mem_init(cinfo); /* system-dependent initialization */
/* Attempt to allocate memory manager's control block */
mem = (my_mem_ptr) jpeg_get_small(cinfo, SIZEOF(my_memory_mgr));
if (mem == NULL) {
jpeg_mem_term(cinfo); /* system-dependent cleanup */
ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 0);
}
/* OK, fill in the method pointers */
mem->pub.alloc_small = alloc_small;
mem->pub.alloc_large = alloc_large;
mem->pub.alloc_sarray = alloc_sarray;
mem->pub.alloc_barray = alloc_barray;
mem->pub.request_virt_sarray = request_virt_sarray;
mem->pub.request_virt_barray = request_virt_barray;
mem->pub.realize_virt_arrays = realize_virt_arrays;
mem->pub.access_virt_sarray = access_virt_sarray;
mem->pub.access_virt_barray = access_virt_barray;
mem->pub.free_pool = free_pool;
mem->pub.self_destruct = self_destruct;
/* Make MAX_ALLOC_CHUNK accessible to other modules */
mem->pub.max_alloc_chunk = MAX_ALLOC_CHUNK;
/* Initialize working state */
mem->pub.max_memory_to_use = max_to_use;
for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) {
mem->small_list[pool] = NULL;
mem->large_list[pool] = NULL;
}
mem->virt_sarray_list = NULL;
mem->virt_barray_list = NULL;
mem->total_space_allocated = SIZEOF(my_memory_mgr);
/* Declare ourselves open for business */
cinfo->mem = & mem->pub;
/* Check for an environment variable JPEGMEM; if found, override the
* default max_memory setting from jpeg_mem_init. Note that the
* surrounding application may again override this value.
* If your system doesn't support getenv(), define NO_GETENV to disable
* this feature.
*/
#ifndef NO_GETENV
{ char * memenv;
if ((memenv = getenv("JPEGMEM")) != NULL) {
char ch = 'x';
if (sscanf(memenv, "%ld%c", &max_to_use, &ch) > 0) {
if (ch == 'm' || ch == 'M')
max_to_use *= 1000L;
mem->pub.max_memory_to_use = max_to_use * 1000L;
}
}
}
#endif
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -