// Starting at "start_addr" (inclusive) return a memory region // corresponding to the first maximal contiguous marked ("1") region // strictly less than end_addr. inline MemRegion CMSBitMap::getAndClearMarkedRegion(HeapWord* start_addr, HeapWord* end_addr) { HeapWord *start, *end; assert_locked(); start = getNextMarkedWordAddress (start_addr, end_addr); end = getNextUnmarkedWordAddress(start, end_addr); assert(start <= end, "Consistency check"); MemRegion mr(start, end); if (!mr.is_empty()) { clear_range(mr); } return mr; }
// Return the HeapWord address corrsponding to the next "0" bit // (inclusive). inline HeapWord* CMSBitMap::getNextUnmarkedWordAddress( HeapWord* start_addr, HeapWord* end_addr) const { assert_locked(); size_t nextOffset = _bm.get_next_zero_offset( heapWordToOffset(start_addr), heapWordToOffset(end_addr)); HeapWord* nextAddr = offsetToHeapWord(nextOffset); assert(nextAddr >= start_addr && nextAddr <= end_addr, "get_next_zero postcondition"); assert((nextAddr == end_addr) || isUnmarked(nextAddr), "get_next_zero postcondition"); return nextAddr; }
/************************************************************************** * Stop (Private) * * Lock must be held. **************************************************************************/ static void stop(libvlc_media_list_player_t * p_mlp, libvlc_exception_t * p_e) { assert_locked(p_mlp); if (p_mlp->p_mi && p_mlp->current_playing_item_path) { /* We are not interested in getting media stop event now */ uninstall_media_player_observer(p_mlp); libvlc_media_player_stop(p_mlp->p_mi, p_e); install_media_player_observer(p_mlp); } free(p_mlp->current_playing_item_path); p_mlp->current_playing_item_path = NULL; }
/************************************************************************** * uninstall_media_player_observer (private) **************************************************************************/ static void uninstall_media_player_observer(libvlc_media_list_player_t * p_mlp) { assert_locked(p_mlp); // Allow callbacks to run, because detach() will wait until all callbacks are processed. // This is safe because only callbacks are allowed, and there execution will be cancelled. vlc_mutex_unlock(&p_mlp->mp_callback_lock); libvlc_event_detach(mplayer_em(p_mlp), libvlc_MediaPlayerEndReached, media_player_reached_end, p_mlp); // Now, lock back the callback lock. No more callback will be present from this point. vlc_mutex_lock(&p_mlp->mp_callback_lock); // What is here is safe, because we guarantee that we won't be able to anything concurrently, // - except (cancelled) callbacks - thanks to the object_lock. }
/************************************************************************** * Stop (Private) * * Lock must be held. **************************************************************************/ static void stop(libvlc_media_list_player_t * p_mlp) { assert_locked(p_mlp); /* We are not interested in getting media stop event now */ uninstall_media_player_observer(p_mlp); libvlc_media_player_stop(p_mlp->p_mi); install_media_player_observer(p_mlp); free(p_mlp->current_playing_item_path); p_mlp->current_playing_item_path = NULL; /* Send the event */ libvlc_event_t event; event.type = libvlc_MediaListPlayerStopped; libvlc_event_send(&p_mlp->event_manager, &event); }
/************************************************************************** * Set relative playlist position and play (Private) * * Sets the currently played item to the given relative play item position * (based on the currently playing item) and then begins the new item playback. * Lock must be held. **************************************************************************/ static void set_relative_playlist_position_and_play( libvlc_media_list_player_t * p_mlp, int i_relative_position, libvlc_exception_t * p_e) { assert_locked(p_mlp); if (!p_mlp->p_mlist) { libvlc_exception_raise(p_e); libvlc_printerr("No media list"); return; } libvlc_media_list_lock(p_mlp->p_mlist); libvlc_media_list_path_t path = p_mlp->current_playing_item_path; if(p_mlp->e_playback_mode != libvlc_playback_mode_repeat) { bool b_loop = (p_mlp->e_playback_mode == libvlc_playback_mode_loop); if(i_relative_position > 0) { do { path = get_next_path(p_mlp, b_loop); set_current_playing_item(p_mlp, path); --i_relative_position; } while(i_relative_position > 0); } else if(i_relative_position < 0) { do { path = get_previous_path(p_mlp, b_loop); set_current_playing_item(p_mlp, path); ++i_relative_position; } while (i_relative_position < 0); } } else { set_current_playing_item(p_mlp, path); } #ifdef DEBUG_MEDIA_LIST_PLAYER printf("Playing:"); libvlc_media_list_path_dump(path); #endif if (!path) { libvlc_media_list_unlock(p_mlp->p_mlist); stop(p_mlp, p_e); return; } libvlc_media_player_play(p_mlp->p_mi, p_e); libvlc_media_list_unlock(p_mlp->p_mlist); /* Send the next item event */ libvlc_event_t event; event.type = libvlc_MediaListPlayerNextItemSet; libvlc_media_t * p_md = libvlc_media_list_item_at_path(p_mlp->p_mlist, path); event.u.media_list_player_next_item_set.item = p_md; libvlc_event_send(p_mlp->p_event_manager, &event); libvlc_media_release(p_md); }
inline bool CMSBitMap::isUnmarked(HeapWord* addr) const { assert_locked(); assert(_bmStartWord <= addr && addr < (_bmStartWord + _bmWordSize), "outside underlying space?"); return !_bm.at(heapWordToOffset(addr)); }
/************************************************************************** * install_media_player_observer (private) **************************************************************************/ static void install_media_player_observer(libvlc_media_list_player_t * p_mlp) { assert_locked(p_mlp); libvlc_event_attach_async(mplayer_em(p_mlp), libvlc_MediaPlayerEndReached, media_player_reached_end, p_mlp, NULL); }
/************************************************************************** * install_playlist_observer (private) **************************************************************************/ static void install_playlist_observer(libvlc_media_list_player_t * p_mlp) { assert_locked(p_mlp); libvlc_event_attach(mlist_em(p_mlp), libvlc_MediaListItemDeleted, mlist_item_deleted, p_mlp, NULL); }
/************************************************************************** * get_previous_path (private) * * Returns the path to the preceding item in the list. * If looping is specified and the current item is the first list item in * the list it will return the last descendant of the last item in the list. **************************************************************************/ static libvlc_media_list_path_t get_previous_path(libvlc_media_list_player_t * p_mlp, bool b_loop) { assert_locked(p_mlp); /* We are entered with libvlc_media_list_lock(p_mlp->p_list) */ libvlc_media_list_path_t ret; libvlc_media_list_t * p_parent_of_playing_item; if (!p_mlp->current_playing_item_path) { if (!libvlc_media_list_count(p_mlp->p_mlist, NULL)) return NULL; return libvlc_media_list_path_with_root_index(0); } /* Try to catch parent element */ p_parent_of_playing_item = libvlc_media_list_parentlist_at_path( p_mlp->p_mlist, p_mlp->current_playing_item_path); int depth = libvlc_media_list_path_depth(p_mlp->current_playing_item_path); if (depth < 1 || !p_parent_of_playing_item) return NULL; /* Set the return path to the current path */ ret = libvlc_media_list_path_copy(p_mlp->current_playing_item_path); /* Change the return path to the previous list entry */ ret[depth - 1]--; /* set to previous element */ ret[depth] = -1; /* Is the return path is beyond the start of the current list? */ if(ret[depth - 1] < 0) { /* Move to parent of current item */ depth--; /* Are we at the root level of the tree? */ if (depth <= 0) { // Is looping enabled? if(b_loop) { int i_count = libvlc_media_list_count(p_parent_of_playing_item, NULL); /* Set current play item to the last element in the list */ ret[0] = i_count - 1; ret[1] = -1; /* Set the return path to the last descendant item of the current item */ ret = find_last_item(p_mlp->p_mlist, ret); } else { /* No looping so return empty path. */ free(ret); ret = NULL; } } else { /* This is the case of moving backward from the beginning of the * subitem list to its parent item. * This ensures that current path is properly terminated to * use that parent. */ ret[depth] = -1; } } else { ret = find_last_item(p_mlp->p_mlist, ret); } libvlc_media_list_release(p_parent_of_playing_item); return ret; }
/************************************************************************** * get_next_path (private) * * Returns the path to the next item in the list. * If looping is specified and the current item is the last list item in * the list it will return the first item in the list. **************************************************************************/ static libvlc_media_list_path_t get_next_path(libvlc_media_list_player_t * p_mlp, bool b_loop) { assert_locked(p_mlp); /* We are entered with libvlc_media_list_lock(p_mlp->p_list) */ libvlc_media_list_path_t ret; libvlc_media_list_t * p_parent_of_playing_item; libvlc_media_list_t * p_sublist_of_playing_item; if (!p_mlp->current_playing_item_path) { if (!libvlc_media_list_count(p_mlp->p_mlist, NULL)) return NULL; return libvlc_media_list_path_with_root_index(0); } p_sublist_of_playing_item = libvlc_media_list_sublist_at_path( p_mlp->p_mlist, p_mlp->current_playing_item_path); /* If item just gained a sublist just play it */ if (p_sublist_of_playing_item) { libvlc_media_list_release(p_sublist_of_playing_item); return libvlc_media_list_path_copy_by_appending(p_mlp->current_playing_item_path, 0); } /* Try to catch parent element */ p_parent_of_playing_item = libvlc_media_list_parentlist_at_path(p_mlp->p_mlist, p_mlp->current_playing_item_path); int depth = libvlc_media_list_path_depth(p_mlp->current_playing_item_path); if (depth < 1 || !p_parent_of_playing_item) return NULL; ret = libvlc_media_list_path_copy(p_mlp->current_playing_item_path); ret[depth - 1]++; /* set to next element */ /* If this goes beyond the end of the list */ while(ret[depth-1] >= libvlc_media_list_count(p_parent_of_playing_item, NULL)) { depth--; if (depth <= 0) { if(b_loop) { ret[0] = 0; ret[1] = -1; break; } else { free(ret); libvlc_media_list_release(p_parent_of_playing_item); return NULL; } } ret[depth] = -1; ret[depth-1]++; p_parent_of_playing_item = libvlc_media_list_parentlist_at_path( p_mlp->p_mlist, ret); } libvlc_media_list_release(p_parent_of_playing_item); return ret; }
static inline libvlc_event_manager_t * mplayer_em(libvlc_media_list_player_t * p_mlp) { assert_locked(p_mlp); return libvlc_media_player_event_manager(p_mlp->p_mi, NULL); }
static void assert_locked(const Mutex* lock) { assert_locked(lock, NULL); }
inline void CMSBitMap::par_clear(HeapWord* addr) { assert_locked(); assert(_bmStartWord <= addr && addr < (_bmStartWord + _bmWordSize), "outside underlying space?"); _bm.par_at_put(heapWordToOffset(addr), false); }
inline bool CMSBitMap::par_mark(HeapWord* addr) { assert_locked(); assert(_bmStartWord <= addr && addr < (_bmStartWord + _bmWordSize), "outside underlying space?"); return _bm.par_at_put(heapWordToOffset(addr), true); }
inline void CMSBitMap::mark(HeapWord* addr) { assert_locked(); assert(_bmStartWord <= addr && addr < (_bmStartWord + _bmWordSize), "outside underlying space?"); _bm.set_bit(heapWordToOffset(addr)); }
inline void CMSBitMap::clear_all() { assert_locked(); // CMS bitmaps are usually cover large memory regions _bm.clear_large(); return; }
inline bool CMSBitMap::isAllClear() const { assert_locked(); return getNextMarkedWordAddress(startWord()) >= endWord(); }